changeset 11933:60bf1372d1a0

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 07 Oct 2013 23:16:00 +0200
parents 66909d055314 (diff) b7ce25d81ef3 (current diff)
children dca16d6f9d65 12e119095ac8
files graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PhiStampPhase.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceLoadFinalPhase.java
diffstat 30 files changed, 502 insertions(+), 526 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ObjectLocationIdentity.java	Mon Oct 07 23:16:00 2013 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, 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.api.meta;
+
+import java.util.*;
+
+/**
+ * A {@link LocationIdentity} warpping an object.
+ */
+public final class ObjectLocationIdentity implements LocationIdentity {
+
+    private static IdentityHashMap<Object, LocationIdentity> map = new IdentityHashMap<>();
+
+    private Object object;
+
+    public static LocationIdentity create(Object object) {
+        synchronized (map) {
+            if (map.containsKey(object)) {
+                return map.get(object);
+            } else {
+                ObjectLocationIdentity locationIdentity = new ObjectLocationIdentity(object);
+                map.put(object, locationIdentity);
+                return locationIdentity;
+            }
+        }
+    }
+
+    private ObjectLocationIdentity(Object object) {
+        this.object = object;
+    }
+
+    @Override
+    public String toString() {
+        return "Identity(" + object + ")";
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Mon Oct 07 23:16:00 2013 +0200
@@ -29,7 +29,7 @@
  * Represents a reference to a resolved Java field. Fields, like methods and types, are resolved
  * through {@link ConstantPool constant pools}.
  */
-public interface ResolvedJavaField extends JavaField {
+public interface ResolvedJavaField extends JavaField, LocationIdentity {
 
     /**
      * Returns the Java language modifiers for this field, as an integer. The {@link Modifier} class
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Mon Oct 07 23:16:00 2013 +0200
@@ -229,7 +229,7 @@
     public static class SingleOperandFormat {
 
         protected Variable dest;
-        protected Value    source;
+        protected Value source;
 
         public SingleOperandFormat(Variable dst, Value src) {
             setDestination(dst);
@@ -340,8 +340,7 @@
 
         @Override
         public String emit() {
-            return (typeForKind(dest.getKind()) + "." + typeForKind(source.getKind()) + " " +
-                    emitVariable(dest) + ", " + emitValue(source) + ";");
+            return (typeForKind(dest.getKind()) + "." + typeForKind(source.getKind()) + " " + emitVariable(dest) + ", " + emitValue(source) + ";");
         }
     }
 
@@ -367,21 +366,18 @@
 
         @Override
         public String emitRegister(Variable var, boolean comma) {
-            /* if (space == Parameter) {
-                return ("param" + var.index);
-            } else {
-                return ("%r" + var.index);
-            } */
+            /*
+             * if (space == Parameter) { return ("param" + var.index); } else { return ("%r" +
+             * var.index); }
+             */
             return ("%r" + var.index);
         }
 
         public String emit(boolean isLoad) {
             if (isLoad) {
-                return (space.getStateName() + "." + typeForKind(valueKind) + " " +
-                        emitRegister(dest, false) + ", " + emitAddress(source1, source2) + ";");
+                return (space.getStateName() + "." + typeForKind(valueKind) + " " + emitRegister(dest, false) + ", " + emitAddress(source1, source2) + ";");
             } else {
-                return (space.getStateName() + "." + typeForKind(valueKind) + " " +
-                        emitAddress(source1, source2) + ", " + emitRegister(dest, false) + ";");
+                return (space.getStateName() + "." + typeForKind(valueKind) + " " + emitAddress(source1, source2) + ", " + emitRegister(dest, false) + ";");
             }
         }
     }
@@ -546,7 +542,7 @@
             }
         }
     }
-    
+
     public static class Mov extends SingleOperandFormat {
 
         private int predicateRegisterNumber = -1;
@@ -559,16 +555,15 @@
             super(dst, src);
             this.predicateRegisterNumber = predicate;
         }
+
         /*
-        public Mov(Variable dst, AbstractAddress src) {
-            throw GraalInternalError.unimplemented("AbstractAddress Mov");
-        }
-        */
-        
+         * public Mov(Variable dst, AbstractAddress src) { throw
+         * GraalInternalError.unimplemented("AbstractAddress Mov"); }
+         */
+
         public void emit(PTXAssembler asm) {
             if (predicateRegisterNumber >= 0) {
-                asm.emitString("@%p" + String.valueOf(predicateRegisterNumber)
-                               + " mov." + super.emit());
+                asm.emitString("@%p" + String.valueOf(predicateRegisterNumber) + " mov." + super.emit());
             } else {
                 asm.emitString("mov." + super.emit());
             }
@@ -585,7 +580,7 @@
             asm.emitString("neg." + super.emit());
         }
     }
-    
+
     public static class Not extends BinarySingleOperandFormat {
 
         public Not(Variable dst, Variable src) {
@@ -596,7 +591,7 @@
             asm.emitString("not." + super.emit());
         }
     }
-    
+
     public static class Ld extends LoadStoreFormat {
 
         public Ld(PTXStateSpace space, Variable dst, Variable src1, Value src2) {
@@ -651,7 +646,7 @@
 
             for (int i = 0; i < refs.length; i++) {
                 sb.append(asm.nameOf(refs[i].label()));
-                if (i < (refs.length -1)) {
+                if (i < (refs.length - 1)) {
                     sb.append(", ");
                 }
             }
@@ -660,9 +655,7 @@
         }
 
         public void emit(PTXAssembler asm) {
-            asm.emitString(".global ." + valueForKind(kind) +
-                           " " + name + "[" + targets.length + "] = " +
-                           "{ " + emitTargets(asm, targets) + " };");
+            asm.emitString(".global ." + valueForKind(kind) + " " + name + "[" + targets.length + "] = " + "{ " + emitTargets(asm, targets) + " };");
         }
     }
 
@@ -684,7 +677,7 @@
         }
 
         public void emit(PTXAssembler asm) {
-            asm.emitString(".param ." + paramForKind(dest.getKind()) + emitParameter(dest)  + (lastParameter ? "" : ","));
+            asm.emitString(".param ." + paramForKind(dest.getKind()) + emitParameter(dest) + (lastParameter ? "" : ","));
         }
 
         public String paramForKind(Kind k) {
@@ -730,9 +723,7 @@
     }
 
     public enum BooleanOperator {
-        AND("and"),
-        OR("or"),
-        XOR("xor");
+        AND("and"), OR("or"), XOR("xor");
 
         private final String output;
 
@@ -745,18 +736,15 @@
         }
     }
 
-    public static class Setp  {
-
+    public static class Setp {
 
-        private BooleanOperator    booleanOperator;
-        private ConditionOperator  operator;
+        private BooleanOperator booleanOperator;
+        private ConditionOperator operator;
         private Value first, second;
         private Kind kind;
         private int predicate;
 
-        public Setp(Condition condition,
-                    Value first, Value second,
-                    int predicateRegisterNumber) {
+        public Setp(Condition condition, Value first, Value second, int predicateRegisterNumber) {
             setFirst(first);
             setSecond(second);
             setPredicate(predicateRegisterNumber);
@@ -764,9 +752,7 @@
             setConditionOperator(operatorForConditon(condition));
         }
 
-        public Setp(Condition condition, BooleanOperator operator,
-                    Value first, Value second,
-                    int predicateRegisterNumber) {
+        public Setp(Condition condition, BooleanOperator operator, Value first, Value second, int predicateRegisterNumber) {
             setFirst(first);
             setSecond(second);
             setPredicate(predicateRegisterNumber);
@@ -804,12 +790,18 @@
                 case 'a':
                     // unsigned
                     switch (condition) {
-                        case EQ: return ConditionOperator.U_EQ;
-                        case NE: return ConditionOperator.U_NE;
-                        case LT: return ConditionOperator.U_LO;
-                        case LE: return ConditionOperator.U_LS;
-                        case GT: return ConditionOperator.U_HI;
-                        case GE: return ConditionOperator.U_HS;
+                        case EQ:
+                            return ConditionOperator.U_EQ;
+                        case NE:
+                            return ConditionOperator.U_NE;
+                        case LT:
+                            return ConditionOperator.U_LO;
+                        case LE:
+                            return ConditionOperator.U_LS;
+                        case GT:
+                            return ConditionOperator.U_HI;
+                        case GE:
+                            return ConditionOperator.U_HS;
                         default:
                             throw GraalInternalError.shouldNotReachHere();
                     }
@@ -819,11 +811,16 @@
                 case 'j':
                     // signed
                     switch (condition) {
-                        case EQ: return ConditionOperator.S_EQ;
-                        case NE: return ConditionOperator.S_NE;
-                        case LT: return ConditionOperator.S_LT;
-                        case LE: return ConditionOperator.S_LE;
-                        case GT: return ConditionOperator.S_GT;
+                        case EQ:
+                            return ConditionOperator.S_EQ;
+                        case NE:
+                            return ConditionOperator.S_NE;
+                        case LT:
+                            return ConditionOperator.S_LT;
+                        case LE:
+                            return ConditionOperator.S_LE;
+                        case GT:
+                            return ConditionOperator.S_GT;
                         case GE:
                         case AE:
                             return ConditionOperator.S_GE;
@@ -834,12 +831,18 @@
                 case 'd':
                     // floating point - do these need to accept NaN??
                     switch (condition) {
-                        case EQ: return ConditionOperator.F_EQ;
-                        case NE: return ConditionOperator.F_NE;
-                        case LT: return ConditionOperator.F_LT;
-                        case LE: return ConditionOperator.F_LE;
-                        case GT: return ConditionOperator.F_GT;
-                        case GE: return ConditionOperator.F_GE;
+                        case EQ:
+                            return ConditionOperator.F_EQ;
+                        case NE:
+                            return ConditionOperator.F_NE;
+                        case LT:
+                            return ConditionOperator.F_LT;
+                        case LE:
+                            return ConditionOperator.F_LE;
+                        case GT:
+                            return ConditionOperator.F_GT;
+                        case GE:
+                            return ConditionOperator.F_GE;
                         default:
                             throw GraalInternalError.shouldNotReachHere();
                     }
@@ -857,7 +860,7 @@
                 kind = first.getKind();
             }
         }
-        
+
         public String emitValue(Value v) {
             assert v != null;
 
@@ -909,7 +912,7 @@
                     throw GraalInternalError.shouldNotReachHere();
             }
         }
-        
+
         public String emitVariable(Variable v) {
             return ("%r" + v.index);
         }
@@ -917,21 +920,15 @@
         public void emit(PTXAssembler asm) {
 
             if (booleanOperator != null) {
-                asm.emitString("setp." +
-                               operator.getOperator() + "." +
-                               booleanOperator.getOperator() +
-                               typeForKind(kind) + " %p" + predicate +
-                               emitValue(first) + emitValue(second) +
-                               ", %r;"); // Predicates need to be objects
+                asm.emitString("setp." + operator.getOperator() + "." + booleanOperator.getOperator() + typeForKind(kind) + " %p" + predicate + emitValue(first) + emitValue(second) + ", %r;"); // Predicates
+// need to be objects
 
             } else {
-                asm.emitString("setp." +
-                               operator.getOperator() + "." +
-                               typeForKind(kind) + " %p" + predicate +
-                               emitValue(first) + emitValue(second) + ";");
+                asm.emitString("setp." + operator.getOperator() + "." + typeForKind(kind) + " %p" + predicate + emitValue(first) + emitValue(second) + ";");
             }
         }
     }
+
     @Override
     public PTXAddress makeAddress(Register base, int displacement) {
         throw GraalInternalError.shouldNotReachHere();
@@ -951,5 +948,4 @@
         bra(str);
     }
 
-
 }
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Mon Oct 07 23:16:00 2013 +0200
@@ -24,7 +24,6 @@
 
 import java.lang.reflect.Method;
 
-import org.junit.Ignore;
 import org.junit.Test;
 
 /**
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java	Mon Oct 07 23:16:00 2013 +0200
@@ -36,7 +36,7 @@
         } else {
             printReport("testLoop: no VALUE");
         }
-        ret =  (Integer) invoke(compile("testSwitchDefault1I"), 3);
+        ret = (Integer) invoke(compile("testSwitchDefault1I"), 3);
         if (ret != null) {
             printReport("testSwitchDefault1I: " + ret);
         } else {
@@ -96,7 +96,7 @@
     }
 
     public static int testIfElse2I(int c, int y) {
-        if  (c > 19) {
+        if (c > 19) {
             return 'M';    // millenial
         } else if (y > 84) {
             return 'Y';    // young
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Oct 07 23:16:00 2013 +0200
@@ -66,7 +66,6 @@
 
 import java.lang.annotation.*;
 
-
 /**
  * This class implements the PTX specific portion of the LIR generator.
  */
@@ -88,9 +87,7 @@
         }
     }
 
-    public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime,
-                           TargetDescription target, FrameMap frameMap,
-                           CallingConvention cc, LIR lir) {
+    public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) {
         super(graph, runtime, target, frameMap, cc, lir);
         lir.spillMoveFactory = new PTXSpillMoveFactory();
         int callVariables = cc.getArgumentCount() + (cc.getReturn() == Value.ILLEGAL ? 0 : 1);
@@ -127,9 +124,7 @@
             if (isRegister(value)) {
                 return asRegister(value).asValue(value.getKind().getStackKind());
             } else if (isStackSlot(value)) {
-                return StackSlot.get(value.getKind().getStackKind(),
-                                     asStackSlot(value).getRawOffset(),
-                                     asStackSlot(value).getRawAddFrameSize());
+                return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize());
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
@@ -339,9 +334,7 @@
     }
 
     @Override
-    public Variable emitConditionalMove(Value left, Value right,
-                                        Condition cond, boolean unorderedIsTrue,
-                                        Value trueValue, Value falseValue) {
+    public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
 
         Condition finalCondition = LIRValueUtil.isVariable(right) ? cond.mirror() : cond;
 
@@ -352,16 +345,12 @@
             case Int:
             case Long:
             case Object:
-                append(new CondMoveOp(result, finalCondition,
-                                      load(trueValue), loadNonConst(falseValue),
-                                      nextPredRegNum));
+                append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue), nextPredRegNum));
                 nextPredRegNum++;
                 break;
             case Float:
             case Double:
-                append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue,
-                                           load(trueValue), load(falseValue),
-                                           nextPredRegNum));
+                append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue), nextPredRegNum));
                 nextPredRegNum++;
                 break;
             default:
@@ -371,9 +360,9 @@
     }
 
     /**
-     * This method emits the compare instruction, and may reorder the operands. 
-     * It returns true if it did so.
-     *
+     * This method emits the compare instruction, and may reorder the operands. It returns true if
+     * it did so.
+     * 
      * @param a the left operand of the comparison
      * @param b the right operand of the comparison
      * @return true if the left and right operands were switched, false otherwise
@@ -413,7 +402,6 @@
         return mirrored;
     }
 
-
     @Override
     public Variable emitIntegerTestMove(Value left, Value right,
                                         Value trueValue, Value falseValue) {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Oct 07 23:16:00 2013 +0200
@@ -157,7 +157,7 @@
     }
 
     public static Object test5Snippet() throws Exception {
-        return UnsafeLoadNode.load(wr, 0, useCompressedOops() ? 12 : 16, Kind.Object);
+        return UnsafeLoadNode.load(wr, useCompressedOops() ? 12 : 16, Kind.Object);
     }
 
     /**
@@ -232,7 +232,7 @@
     public static Object testUnsafeLoad(Object a, Object b, Object c) throws Exception {
         final int offset = (c == null ? 0 : ((Integer) c).intValue());
         final long displacement = (b == null ? 0 : ((Long) b).longValue());
-        return UnsafeLoadNode.load(a, offset, displacement, Kind.Object);
+        return UnsafeLoadNode.load(a, offset + displacement, Kind.Object);
     }
 
     private HotSpotInstalledCode getInstalledCode(String name) throws Exception {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Oct 07 23:16:00 2013 +0200
@@ -654,7 +654,7 @@
                 if (addReadBarrier(load)) {
                     unsafeLoadSnippets.lower(load, tool);
                 } else {
-                    IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1);
+                    LocationNode location = createLocation(load);
                     ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), BarrierType.NONE, compressible));
                     // An unsafe read must not float outside its block otherwise
                     // it may float above an explicit null check on its object.
@@ -664,7 +664,7 @@
             }
         } else if (n instanceof UnsafeStoreNode) {
             UnsafeStoreNode store = (UnsafeStoreNode) n;
-            IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1);
+            LocationNode location = createLocation(store);
             ValueNode object = store.object();
             BarrierType barrierType = getUnsafeStoreBarrierType(store);
             WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().kind() == Kind.Object));
@@ -857,6 +857,43 @@
         }
     }
 
+    private static LocationNode createLocation(UnsafeAccessNode access) {
+        ValueNode offset = access.offset();
+        if (offset.isConstant()) {
+            long offsetValue = offset.asConstant().asLong();
+            return ConstantLocationNode.create(access.getLocationIdentity(), access.accessKind(), offsetValue, access.graph());
+        }
+
+        long displacement = 0;
+        int indexScaling = 1;
+        if (offset instanceof IntegerAddNode) {
+            IntegerAddNode integerAddNode = (IntegerAddNode) offset;
+            if (integerAddNode.y() instanceof ConstantNode) {
+                displacement = integerAddNode.y().asConstant().asLong();
+                offset = integerAddNode.x();
+            }
+        }
+
+        if (offset instanceof LeftShiftNode) {
+            LeftShiftNode leftShiftNode = (LeftShiftNode) offset;
+            if (leftShiftNode.y() instanceof ConstantNode) {
+                long shift = leftShiftNode.y().asConstant().asLong();
+                if (shift >= 1 && shift <= 3) {
+                    if (shift == 1) {
+                        indexScaling = 2;
+                    } else if (shift == 2) {
+                        indexScaling = 4;
+                    } else {
+                        indexScaling = 8;
+                    }
+                    offset = leftShiftNode.x();
+                }
+            }
+        }
+
+        return IndexedLocationNode.create(access.getLocationIdentity(), access.accessKind(), displacement, offset, access.graph(), indexScaling);
+    }
+
     private static boolean addReadBarrier(UnsafeLoadNode load) {
         if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().kind() == Kind.Object && load.accessKind() == Kind.Object &&
                         !ObjectStamp.isObjectAlwaysNull(load.object())) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Mon Oct 07 23:16:00 2013 +0200
@@ -66,7 +66,7 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) {
-        Object kObject = UnsafeLoadNode.load(rcvr, 0, kOffset, Kind.Object);
+        Object kObject = UnsafeLoadNode.load(rcvr, kOffset, Kind.Object);
         Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Mon Oct 07 23:16:00 2013 +0200
@@ -62,7 +62,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = UnsafeLoadNode.load(rcvr, 0, embeddedCipherOffset, Kind.Object);
+        Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object);
         if (getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, true);
         } else {
@@ -72,7 +72,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = UnsafeLoadNode.load(rcvr, 0, embeddedCipherOffset, Kind.Object);
+        Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object);
         if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, false);
         } else {
@@ -81,8 +81,8 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) {
-        Object kObject = UnsafeLoadNode.load(embeddedCipher, 0, AESCryptSubstitutions.kOffset, Kind.Object);
-        Object rObject = UnsafeLoadNode.load(rcvr, 0, rOffset, Kind.Object);
+        Object kObject = UnsafeLoadNode.load(embeddedCipher, AESCryptSubstitutions.kOffset, Kind.Object);
+        Object rObject = UnsafeLoadNode.load(rcvr, rOffset, Kind.Object);
         Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte));
         Word rAddr = (Word) Word.fromObject(rObject).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Oct 07 23:16:00 2013 +0200
@@ -481,7 +481,7 @@
 
     public static Word loadWordFromObject(Object object, int offset) {
         assert offset != hubOffset() : "Use loadHubIntrinsic instead";
-        return loadWordFromObjectIntrinsic(object, 0, offset, getWordKind());
+        return loadWordFromObjectIntrinsic(object, offset, getWordKind());
     }
 
     @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true)
@@ -489,8 +489,8 @@
 
     @SuppressWarnings("unused")
     @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
-    private static Word loadWordFromObjectIntrinsic(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind wordKind) {
-        return Word.unsigned(unsafeReadWord(object, offset + displacement));
+    private static Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind) {
+        return Word.unsigned(unsafeReadWord(object, offset));
     }
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Mon Oct 07 23:16:00 2013 +0200
@@ -86,42 +86,42 @@
             for (long i = 0; i < postLoopBytes; i += elementSize) {
                 srcOffset -= elementSize;
                 destOffset -= elementSize;
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset, srcOffset, baseKind);
-                UnsafeStoreNode.store(dest, arrayBaseOffset, destOffset, a, baseKind);
+                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind);
             }
             // Main-loop
             for (long i = 0; i < mainLoopBytes; i += VECTOR_SIZE) {
                 srcOffset -= VECTOR_SIZE;
                 destOffset -= VECTOR_SIZE;
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset, srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset, destOffset, a.longValue(), VECTOR_KIND);
+                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a.longValue(), VECTOR_KIND);
             }
             // Pre-loop
             for (long i = 0; i < preLoopBytes; i += elementSize) {
                 srcOffset -= elementSize;
                 destOffset -= elementSize;
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset, srcOffset, baseKind);
-                UnsafeStoreNode.store(dest, arrayBaseOffset, destOffset, a, baseKind);
+                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind);
             }
         } else {
             // Pre-loop
             for (long i = 0; i < preLoopBytes; i += elementSize) {
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset, srcOffset, baseKind);
-                UnsafeStoreNode.store(dest, arrayBaseOffset, destOffset, a, baseKind);
+                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind);
                 srcOffset += elementSize;
                 destOffset += elementSize;
             }
             // Main-loop
             for (long i = 0; i < mainLoopBytes; i += VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset, srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset, destOffset, a.longValue(), VECTOR_KIND);
+                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a.longValue(), VECTOR_KIND);
                 srcOffset += VECTOR_SIZE;
                 destOffset += VECTOR_SIZE;
             }
             // Post-loop
             for (long i = 0; i < postLoopBytes; i += elementSize) {
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset, srcOffset, baseKind);
-                UnsafeStoreNode.store(dest, arrayBaseOffset, destOffset, a, baseKind);
+                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind);
                 srcOffset += elementSize;
                 destOffset += elementSize;
             }
@@ -167,13 +167,13 @@
         long destOffset = (long) destPos * arrayIndexScale(baseKind);
         if (src == dest && srcPos < destPos) { // bad aliased case
             for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset, i + destOffset, a.longValue(), VECTOR_KIND);
+                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND);
             }
         } else {
             for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset, i + destOffset, a.longValue(), VECTOR_KIND);
+                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND);
             }
         }
     }
@@ -187,8 +187,8 @@
         long destOffset = (long) destPos * arrayIndexScale(baseKind);
         if (src == dest && srcPos < destPos) { // bad aliased case
             for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset, i + destOffset, a.longValue(), VECTOR_KIND);
+                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND);
             }
         } else {
             for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
@@ -197,8 +197,8 @@
                  * values to be copied atomically, but not long values. For example, on Intel 32-bit
                  * this code is not atomic as long as the vector kind remains Kind.Long.
                  */
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset, i + destOffset, a.longValue(), VECTOR_KIND);
+                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND);
             }
         }
     }
@@ -213,13 +213,13 @@
         if (src == dest && srcPos < destPos) { // bad aliased case
             long start = (long) (length - 1) * scale;
             for (long i = start; i >= 0; i -= scale) {
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset, i + (long) srcPos * scale, Kind.Object);
+                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, Kind.Object);
                 DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a);
             }
         } else {
             long end = (long) length * scale;
             for (long i = 0; i < end; i += scale) {
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset, i + (long) srcPos * scale, Kind.Object);
+                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, Kind.Object);
                 DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a);
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Mon Oct 07 23:16:00 2013 +0200
@@ -39,9 +39,8 @@
 public class UnsafeLoadSnippets implements Snippets {
 
     @Snippet
-    public static Object lowerUnsafeLoad(Object object, long offset, int disp) {
+    public static Object lowerUnsafeLoad(Object object, long displacement) {
         Object fixedObject = FixedValueAnchorNode.getObject(object);
-        long displacement = disp + offset;
         if (object instanceof java.lang.ref.Reference && referentOffset() == displacement) {
             return Word.fromObject(fixedObject).readObject((int) displacement, BarrierType.PRECISE, true);
         } else {
@@ -61,7 +60,6 @@
             Arguments args = new Arguments(unsafeLoad, load.graph().getGuardsStage());
             args.add("object", load.object());
             args.add("offset", load.offset());
-            args.add("disp", load.displacement());
             template(args).instantiate(runtime, load, DEFAULT_REPLACER, args);
         }
     }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Mon Oct 07 23:16:00 2013 +0200
@@ -58,7 +58,8 @@
 
     public static class ReturnNoValOp extends PTXLIRInstruction {
 
-        public ReturnNoValOp() { }
+        public ReturnNoValOp() {
+        }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
@@ -106,9 +107,7 @@
         private final Condition condition;
         private final int predicate;
 
-        public CondMoveOp(Variable result, Condition condition,
-                          Variable trueValue, Value falseValue,
-                          int predicateRegister) {
+        public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue, int predicateRegister) {
             this.result = result;
             this.condition = condition;
             this.trueValue = trueValue;
@@ -118,8 +117,7 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-            cmove(tasm, masm, result, false, condition, false,
-                  trueValue, falseValue, predicate);
+            cmove(tasm, masm, result, false, condition, false, trueValue, falseValue, predicate);
         }
     }
 
@@ -132,10 +130,7 @@
         private final boolean unorderedIsTrue;
         private final int predicate;
 
-        public FloatCondMoveOp(Variable result, Condition condition,
-                               boolean unorderedIsTrue,
-                               Variable trueValue, Variable falseValue,
-                               int predicateRegister) {
+        public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue, int predicateRegister) {
             this.result = result;
             this.condition = condition;
             this.unorderedIsTrue = unorderedIsTrue;
@@ -146,16 +141,12 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-            cmove(tasm, masm, result, true, condition, unorderedIsTrue,
-                  trueValue, falseValue, predicate);
+            cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue, predicate);
         }
     }
 
-    private static void cmove(TargetMethodAssembler tasm, PTXAssembler asm,
-                              Value result, boolean isFloat, Condition condition,
-                              boolean unorderedIsTrue,
-                              Value trueValue, Value falseValue,
-                              int predicateRegister) {
+    private static void cmove(TargetMethodAssembler tasm, PTXAssembler asm, Value result, boolean isFloat, Condition condition, boolean unorderedIsTrue, Value trueValue, Value falseValue,
+                    int predicateRegister) {
         // check that we don't overwrite an input operand before it is used.
         assert !result.equals(trueValue);
 
@@ -186,12 +177,9 @@
         }
     }
 
-    private static void cmove(PTXAssembler asm,
-                              Value result, Value other,
-                              int predicateRegister) {
+    private static void cmove(PTXAssembler asm, Value result, Value other, int predicateRegister) {
         if (isVariable(other)) {
-            assert !asVariable(other).equals(asVariable(result)) :
-                "other already overwritten by previous move";
+            assert !asVariable(other).equals(asVariable(result)) : "other already overwritten by previous move";
 
             switch (other.getKind()) {
                 case Int:
@@ -218,9 +206,7 @@
         // Number of predicate register that would be set by this instruction.
         protected int predRegNum;
 
-        public SequentialSwitchOp(Constant[] keyConstants,
-                                  LabelRef[] keyTargets, LabelRef defaultTarget,
-                                  Value key, Value scratch, int predReg) {
+        public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch, int predReg) {
             assert keyConstants.length == keyTargets.length;
             this.keyConstants = keyConstants;
             this.keyTargets = keyTargets;
@@ -279,9 +265,7 @@
         // Number of predicate register that would be set by this instruction.
         protected int predRegNum;
 
-        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget,
-                             final LabelRef[] targets,
-                             Variable index, Variable scratch, int predReg) {
+        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch, int predReg) {
             this.lowKey = lowKey;
             this.defaultTarget = defaultTarget;
             this.targets = targets;
@@ -292,15 +276,12 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-            tableswitch(tasm, masm, lowKey, defaultTarget, targets,
-                        index, scratch, predRegNum);
+            tableswitch(tasm, masm, lowKey, defaultTarget, targets, index, scratch, predRegNum);
         }
     }
 
     @SuppressWarnings("unused")
-    private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey,
-                                    LabelRef defaultTarget, LabelRef[] targets,
-                                    Value value, Value scratch, int predNum) {
+    private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value value, Value scratch, int predNum) {
         Buffer buf = masm.codeBuffer;
 
         // Compare index against jump table bounds
@@ -322,7 +303,6 @@
         // address of jump table
         int tablePos = buf.position();
 
-
         JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4);
         String name = "jumptable" + jt.position;
 
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXTestOp.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXTestOp.java	Mon Oct 07 23:16:00 2013 +0200
@@ -24,12 +24,10 @@
 
 import static com.oracle.graal.asm.ptx.PTXAssembler.BooleanOperator.*;
 import static com.oracle.graal.asm.ptx.PTXAssembler.*;
-import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.calc.Condition;
 
@@ -47,20 +45,16 @@
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-        emit(tasm, masm, x, y, predicate);
+        emit(masm, x, y, predicate);
     }
 
     @Override
     protected void verify() {
         super.verify();
-        assert (x.getKind() == Kind.Int &&
-                y.getKind().getStackKind() == Kind.Int) ||
-                (x.getKind() == Kind.Long && y.getKind() == Kind.Long) :
-                x + " " + y;
+        assert (x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (x.getKind() == Kind.Long && y.getKind() == Kind.Long) : x + " " + y;
     }
 
-    public static void emit(TargetMethodAssembler tasm, PTXAssembler masm,
-                            Value x, Value y, int predicate) {
+    public static void emit(PTXAssembler masm, Value x, Value y, int predicate) {
         /*
          * This is not yet quite right - as the result for the equivalent in
          * ControlPTXText.testIntegerTestBranch2I is wrong.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Oct 07 23:16:00 2013 +0200
@@ -43,18 +43,6 @@
         super(object, location, stamp, guard, barrierType, compressible);
     }
 
-    public ReadNode(ValueNode object, int displacement, LocationIdentity locationIdentity, Kind kind) {
-        super(object, ConstantLocationNode.create(locationIdentity, kind, displacement, object.graph()), StampFactory.forKind(kind));
-    }
-
-    private ReadNode(ValueNode object, ValueNode location, ValueNode guard) {
-        /*
-         * Used by node intrinsics. Since the initial value for location is a parameter, i.e., a
-         * LocalNode, the constructor cannot use the declared type LocationNode.
-         */
-        super(object, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard, BarrierType.NONE, false);
-    }
-
     @Override
     public void generate(LIRGeneratorTool gen) {
         Value address = location().generateAddress(gen, gen.operand(object()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Mon Oct 07 23:16:00 2013 +0200
@@ -32,26 +32,26 @@
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
-    private final int displacement;
     private final Kind accessKind;
+    private final LocationIdentity locationIdentity;
 
-    public UnsafeAccessNode(Stamp stamp, ValueNode object, int displacement, ValueNode offset, Kind accessKind) {
+    public UnsafeAccessNode(Stamp stamp, ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) {
         super(stamp);
         assert accessKind != null;
         this.object = object;
-        this.displacement = displacement;
         this.offset = offset;
         this.accessKind = accessKind;
+        this.locationIdentity = locationIdentity;
+    }
+
+    public LocationIdentity getLocationIdentity() {
+        return locationIdentity;
     }
 
     public ValueNode object() {
         return object;
     }
 
-    public int displacement() {
-        return displacement;
-    }
-
     public ValueNode offset() {
         return offset;
     }
@@ -62,13 +62,13 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (offset().isConstant()) {
+        if (this.getLocationIdentity() == LocationIdentity.ANY_LOCATION && offset().isConstant()) {
             long constantOffset = offset().asConstant().asLong();
 
             // Try to canonicalize to a field access.
             ResolvedJavaType receiverType = ObjectStamp.typeOrNull(object());
             if (receiverType != null) {
-                ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement() + constantOffset);
+                ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(constantOffset);
                 // No need for checking that the receiver is non-null. The field access includes
                 // the null check and if a field is found, the offset is so small that this is
                 // never a valid access of an arbitrary address.
@@ -76,18 +76,9 @@
                     return cloneAsFieldAccess(field);
                 }
             }
-
-            if (constantOffset != 0 && Integer.MAX_VALUE - displacement() >= constantOffset) {
-                int intDisplacement = (int) (constantOffset + displacement());
-                if (constantOffset == intDisplacement) {
-                    return cloneWithZeroOffset(intDisplacement);
-                }
-            }
         }
         return this;
     }
 
     protected abstract ValueNode cloneAsFieldAccess(ResolvedJavaField field);
-
-    protected abstract ValueNode cloneWithZeroOffset(int intDisplacement);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Mon Oct 07 23:16:00 2013 +0200
@@ -36,16 +36,12 @@
  */
 public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable {
 
-    public UnsafeLoadNode(ValueNode object, int displacement, ValueNode offset, boolean nonNull) {
-        this(nonNull ? StampFactory.objectNonNull() : StampFactory.object(), object, displacement, offset, Kind.Object);
+    public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind) {
+        this(object, offset, accessKind, LocationIdentity.ANY_LOCATION);
     }
 
-    public UnsafeLoadNode(ValueNode object, int displacement, ValueNode offset, Kind accessKind) {
-        this(StampFactory.forKind(accessKind.getStackKind()), object, displacement, offset, accessKind);
-    }
-
-    public UnsafeLoadNode(Stamp stamp, ValueNode object, int displacement, ValueNode offset, Kind accessKind) {
-        super(stamp, object, displacement, offset, accessKind);
+    public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) {
+        super(StampFactory.forKind(accessKind.getStackKind()), object, offset, accessKind, locationIdentity);
     }
 
     @Override
@@ -57,9 +53,9 @@
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object());
         if (state != null && state.getState() == EscapeState.Virtual) {
-            ValueNode indexValue = tool.getReplacedValue(offset());
-            if (indexValue.isConstant()) {
-                long offset = indexValue.asConstant().asLong() + displacement();
+            ValueNode offsetValue = tool.getReplacedValue(offset());
+            if (offsetValue.isConstant()) {
+                long offset = offsetValue.asConstant().asLong();
                 int entryIndex = state.getVirtualObject().entryIndexForOffset(offset);
                 if (entryIndex != -1 && state.getVirtualObject().entryKind(entryIndex) == accessKind()) {
                     tool.replaceWith(state.getEntry(entryIndex));
@@ -73,39 +69,34 @@
         return this.graph().add(new LoadFieldNode(object(), field));
     }
 
-    @Override
-    protected ValueNode cloneWithZeroOffset(int intDisplacement) {
-        return graph().add(new UnsafeLoadNode(this.stamp(), object(), intDisplacement, graph().unique(ConstantNode.forInt(0, graph())), accessKind()));
-    }
-
     @SuppressWarnings("unchecked")
     @NodeIntrinsic
-    public static <T> T load(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind kind) {
+    public static <T> T load(Object object, long offset, @ConstantNodeParameter Kind kind) {
         if (kind == Kind.Boolean) {
-            return (T) (Boolean) unsafe.getBoolean(object, displacement + offset);
+            return (T) (Boolean) unsafe.getBoolean(object, offset);
         }
         if (kind == Kind.Byte) {
-            return (T) (Byte) unsafe.getByte(object, displacement + offset);
+            return (T) (Byte) unsafe.getByte(object, offset);
         }
         if (kind == Kind.Short) {
-            return (T) (Short) unsafe.getShort(object, displacement + offset);
+            return (T) (Short) unsafe.getShort(object, offset);
         }
         if (kind == Kind.Char) {
-            return (T) (Character) unsafe.getChar(object, displacement + offset);
+            return (T) (Character) unsafe.getChar(object, offset);
         }
         if (kind == Kind.Int) {
-            return (T) (Integer) unsafe.getInt(object, displacement + offset);
+            return (T) (Integer) unsafe.getInt(object, offset);
         }
         if (kind == Kind.Float) {
-            return (T) (Float) unsafe.getFloat(object, displacement + offset);
+            return (T) (Float) unsafe.getFloat(object, offset);
         }
         if (kind == Kind.Long) {
-            return (T) (Long) unsafe.getLong(object, displacement + offset);
+            return (T) (Long) unsafe.getLong(object, offset);
         }
         if (kind == Kind.Double) {
-            return (T) (Double) unsafe.getDouble(object, displacement + offset);
+            return (T) (Double) unsafe.getDouble(object, offset);
         }
         assert kind == Kind.Object;
-        return (T) unsafe.getObject(object, displacement + offset);
+        return (T) unsafe.getObject(object, offset);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Oct 07 23:16:00 2013 +0200
@@ -39,12 +39,12 @@
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
 
-    public UnsafeStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, Kind accessKind) {
-        this(StampFactory.forVoid(), object, displacement, offset, value, accessKind);
+    public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind) {
+        this(object, offset, value, accessKind, LocationIdentity.ANY_LOCATION);
     }
 
-    public UnsafeStoreNode(Stamp stamp, ValueNode object, int displacement, ValueNode offset, ValueNode value, Kind accessKind) {
-        super(stamp, object, displacement, offset, accessKind);
+    public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) {
+        super(StampFactory.forVoid(), object, offset, accessKind, locationIdentity);
         assert accessKind != Kind.Void && accessKind != Kind.Illegal;
         this.value = value;
     }
@@ -73,17 +73,12 @@
     }
 
     @Override
-    public LocationIdentity getLocationIdentity() {
-        return LocationIdentity.ANY_LOCATION;
-    }
-
-    @Override
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object());
         if (state != null && state.getState() == EscapeState.Virtual) {
             ValueNode indexValue = tool.getReplacedValue(offset());
             if (indexValue.isConstant()) {
-                long offset = indexValue.asConstant().asLong() + displacement();
+                long offset = indexValue.asConstant().asLong();
                 int entryIndex = state.getVirtualObject().entryIndexForOffset(offset);
                 if (entryIndex != -1 && state.getVirtualObject().entryKind(entryIndex) == accessKind()) {
                     tool.setVirtualEntry(state, entryIndex, value());
@@ -100,13 +95,6 @@
         return storeFieldNode;
     }
 
-    @Override
-    protected ValueNode cloneWithZeroOffset(int intDisplacement) {
-        UnsafeStoreNode unsafeStoreNode = graph().add(new UnsafeStoreNode(stamp(), object(), intDisplacement, ConstantNode.forInt(0, graph()), value(), accessKind()));
-        unsafeStoreNode.setStateAfter(stateAfter());
-        return unsafeStoreNode;
-    }
-
     public FrameState getState() {
         return stateAfter;
     }
@@ -115,55 +103,55 @@
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, @ConstantNodeParameter int displacement, long offset, Object value, @ConstantNodeParameter Kind kind) {
-        unsafe.putObject(object, offset + displacement, value);
+    public static void store(Object object, long offset, Object value, @ConstantNodeParameter Kind kind) {
+        unsafe.putObject(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, @ConstantNodeParameter int displacement, long offset, boolean value, @ConstantNodeParameter Kind kind) {
-        unsafe.putBoolean(object, offset + displacement, value);
+    public static void store(Object object, long offset, boolean value, @ConstantNodeParameter Kind kind) {
+        unsafe.putBoolean(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, @ConstantNodeParameter int displacement, long offset, byte value, @ConstantNodeParameter Kind kind) {
-        unsafe.putByte(object, offset + displacement, value);
+    public static void store(Object object, long offset, byte value, @ConstantNodeParameter Kind kind) {
+        unsafe.putByte(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, @ConstantNodeParameter int displacement, long offset, char value, @ConstantNodeParameter Kind kind) {
-        unsafe.putChar(object, offset + displacement, value);
+    public static void store(Object object, long offset, char value, @ConstantNodeParameter Kind kind) {
+        unsafe.putChar(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, @ConstantNodeParameter int displacement, long offset, double value, @ConstantNodeParameter Kind kind) {
-        unsafe.putDouble(object, offset + displacement, value);
+    public static void store(Object object, long offset, double value, @ConstantNodeParameter Kind kind) {
+        unsafe.putDouble(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, @ConstantNodeParameter int displacement, long offset, float value, @ConstantNodeParameter Kind kind) {
-        unsafe.putFloat(object, offset + displacement, value);
+    public static void store(Object object, long offset, float value, @ConstantNodeParameter Kind kind) {
+        unsafe.putFloat(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, @ConstantNodeParameter int displacement, long offset, int value, @ConstantNodeParameter Kind kind) {
-        unsafe.putInt(object, offset + displacement, value);
+    public static void store(Object object, long offset, int value, @ConstantNodeParameter Kind kind) {
+        unsafe.putInt(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, @ConstantNodeParameter int displacement, long offset, long value, @ConstantNodeParameter Kind kind) {
-        unsafe.putLong(object, offset + displacement, value);
+    public static void store(Object object, long offset, long value, @ConstantNodeParameter Kind kind) {
+        unsafe.putLong(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, @ConstantNodeParameter int displacement, long offset, short value, @ConstantNodeParameter Kind kind) {
-        unsafe.putShort(object, offset + displacement, value);
+    public static void store(Object object, long offset, short value, @ConstantNodeParameter Kind kind) {
+        unsafe.putShort(object, offset, value);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java	Mon Oct 07 23:16:00 2013 +0200
@@ -64,22 +64,22 @@
 
     @MethodSubstitution
     private static Node getNode(Node node, long offset) {
-        return PiNode.piCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), Node.class, false, false);
+        return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object), Node.class, false, false);
     }
 
     @MethodSubstitution
     private static NodeList getNodeList(Node node, long offset) {
-        return PiNode.piCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), NodeList.class, false, false);
+        return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object), NodeList.class, false, false);
     }
 
     @MethodSubstitution
     private static void putNode(Node node, long offset, Node value) {
-        UnsafeStoreNode.store(node, 0, offset, value, Kind.Object);
+        UnsafeStoreNode.store(node, offset, value, Kind.Object);
     }
 
     @MethodSubstitution
     private static void putNodeList(Node node, long offset, NodeList value) {
-        UnsafeStoreNode.store(node, 0, offset, value, Kind.Object);
+        UnsafeStoreNode.store(node, offset, value, Kind.Object);
     }
 
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java	Mon Oct 07 23:16:00 2013 +0200
@@ -53,7 +53,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static Object getObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
-        return UnsafeLoadNode.load(o, 0, offset, Kind.Object);
+        return UnsafeLoadNode.load(o, offset, Kind.Object);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -66,7 +66,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object x) {
-        UnsafeStoreNode.store(o, 0, offset, x, Kind.Object);
+        UnsafeStoreNode.store(o, offset, x, Kind.Object);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -85,7 +85,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static int getInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
-        Integer value = UnsafeLoadNode.load(o, 0, offset, Kind.Int);
+        Integer value = UnsafeLoadNode.load(o, offset, Kind.Int);
         return value;
     }
 
@@ -99,7 +99,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int x) {
-        UnsafeStoreNode.store(o, 0, offset, x, Kind.Int);
+        UnsafeStoreNode.store(o, offset, x, Kind.Int);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -119,7 +119,7 @@
     @MethodSubstitution(isStatic = false)
     public static boolean getBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Boolean result = UnsafeLoadNode.load(o, 0, offset, Kind.Boolean);
+        Boolean result = UnsafeLoadNode.load(o, offset, Kind.Boolean);
         return result;
     }
 
@@ -133,7 +133,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, boolean x) {
-        UnsafeStoreNode.store(o, 0, offset, x, Kind.Boolean);
+        UnsafeStoreNode.store(o, offset, x, Kind.Boolean);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -146,7 +146,7 @@
     @MethodSubstitution(isStatic = false)
     public static byte getByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Byte result = UnsafeLoadNode.load(o, 0, offset, Kind.Byte);
+        Byte result = UnsafeLoadNode.load(o, offset, Kind.Byte);
         return result;
     }
 
@@ -160,7 +160,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, byte x) {
-        UnsafeStoreNode.store(o, 0, offset, x, Kind.Byte);
+        UnsafeStoreNode.store(o, offset, x, Kind.Byte);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -173,7 +173,7 @@
     @MethodSubstitution(isStatic = false)
     public static short getShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Short result = UnsafeLoadNode.load(o, 0, offset, Kind.Short);
+        Short result = UnsafeLoadNode.load(o, offset, Kind.Short);
         return result;
     }
 
@@ -187,7 +187,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, short x) {
-        UnsafeStoreNode.store(o, 0, offset, x, Kind.Short);
+        UnsafeStoreNode.store(o, offset, x, Kind.Short);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -200,7 +200,7 @@
     @MethodSubstitution(isStatic = false)
     public static char getChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Character result = UnsafeLoadNode.load(o, 0, offset, Kind.Char);
+        Character result = UnsafeLoadNode.load(o, offset, Kind.Char);
         return result;
     }
 
@@ -214,7 +214,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, char x) {
-        UnsafeStoreNode.store(o, 0, offset, x, Kind.Char);
+        UnsafeStoreNode.store(o, offset, x, Kind.Char);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -227,7 +227,7 @@
     @MethodSubstitution(isStatic = false)
     public static long getLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Long result = UnsafeLoadNode.load(o, 0, offset, Kind.Long);
+        Long result = UnsafeLoadNode.load(o, offset, Kind.Long);
         return result;
     }
 
@@ -241,7 +241,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long x) {
-        UnsafeStoreNode.store(o, 0, offset, x, Kind.Long);
+        UnsafeStoreNode.store(o, offset, x, Kind.Long);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -261,7 +261,7 @@
     @MethodSubstitution(isStatic = false)
     public static float getFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Float result = UnsafeLoadNode.load(o, 0, offset, Kind.Float);
+        Float result = UnsafeLoadNode.load(o, offset, Kind.Float);
         return result;
     }
 
@@ -275,7 +275,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, float x) {
-        UnsafeStoreNode.store(o, 0, offset, x, Kind.Float);
+        UnsafeStoreNode.store(o, offset, x, Kind.Float);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -288,7 +288,7 @@
     @MethodSubstitution(isStatic = false)
     public static double getDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Double result = UnsafeLoadNode.load(o, 0, offset, Kind.Double);
+        Double result = UnsafeLoadNode.load(o, offset, Kind.Double);
         return result;
     }
 
@@ -302,7 +302,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, double x) {
-        UnsafeStoreNode.store(o, 0, offset, x, Kind.Double);
+        UnsafeStoreNode.store(o, offset, x, Kind.Double);
     }
 
     @MethodSubstitution(isStatic = false)
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Mon Oct 07 23:16:00 2013 +0200
@@ -173,6 +173,8 @@
                     // Convert deopt to guards.
                     new ConvertDeoptimizeToGuardPhase().apply(graph);
 
+                    new EarlyReadEliminationPhase(canonicalizerPhase).apply(graph, context);
+
                     if (!inliningProgress) {
                         break;
                     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameGetNode.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameGetNode.java	Mon Oct 07 23:16:00 2013 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 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.spi.*;
@@ -84,8 +85,9 @@
             ValueNode slotIndex = getSlotOffset(1, tool.getRuntime());
             loadNode = graph().add(new LoadIndexedNode(loadFieldNode, slotIndex, Kind.Object));
         } else {
-            ValueNode slotOffset = getSlotOffset(Unsafe.ARRAY_LONG_INDEX_SCALE, tool.getRuntime());
-            loadNode = graph().add(new UnsafeLoadNode(loadFieldNode, Unsafe.ARRAY_LONG_BASE_OFFSET, slotOffset, getSlotKind()));
+            ValueNode slotOffset = graph().unique(
+                            new IntegerAddNode(Kind.Long, getSlotOffset(Unsafe.ARRAY_LONG_INDEX_SCALE, tool.getRuntime()), ConstantNode.forLong(Unsafe.ARRAY_LONG_BASE_OFFSET, graph())));
+            loadNode = graph().add(new UnsafeLoadNode(loadFieldNode, slotOffset, getSlotKind()));
         }
         structuredGraph.replaceFixedWithFixed(this, loadNode);
         loadFieldNode.lower(tool);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Mon Oct 07 23:16:00 2013 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.truffle.nodes.typesystem;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.truffle.nodes.asserts.*;
+import com.oracle.truffle.api.*;
+
+/**
+ * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class, boolean)}.
+ */
+public class CustomizedUnsafeLoadMacroNode extends NeverPartOfCompilationNode implements Canonicalizable {
+
+    private static final int ARGUMENT_COUNT = 4;
+    private static final int OBJECT_ARGUMENT_INDEX = 0;
+    private static final int OFFSET_ARGUMENT_INDEX = 1;
+    private static final int CONDITION_ARGUMENT_INDEX = 2;
+    private static final int LOCATION_ARGUMENT_INDEX = 3;
+
+    public CustomizedUnsafeLoadMacroNode(Invoke invoke) {
+        super(invoke, "The location argument could not be resolved to a constant.");
+        assert arguments.size() == ARGUMENT_COUNT;
+    }
+
+    @SuppressWarnings("unused")
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        ValueNode locationArgument = arguments.get(LOCATION_ARGUMENT_INDEX);
+        if (locationArgument.isConstant()) {
+            ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX);
+            ValueNode offsetArgument = arguments.get(OFFSET_ARGUMENT_INDEX);
+            ValueNode conditionArgument = arguments.get(CONDITION_ARGUMENT_INDEX);
+            Object locationIdentityObject = locationArgument.asConstant().asObject();
+            LocationIdentity locationIdentity;
+            if (locationIdentityObject == null) {
+                locationIdentity = LocationIdentity.ANY_LOCATION;
+            } else {
+                locationIdentity = ObjectLocationIdentity.create(locationIdentityObject);
+            }
+            return graph().add(new UnsafeLoadNode(objectArgument, offsetArgument, this.stamp().kind(), locationIdentity));
+        }
+        return this;
+    }
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadNode.java	Mon Oct 07 14:47:18 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2012, 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.truffle.nodes.typesystem;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-
-public final class CustomizedUnsafeLoadNode extends UnsafeLoadNode {
-
-    @Input private ValueNode condition;
-    @Input private ValueNode locationIdentity;
-
-    public CustomizedUnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, ValueNode condition, ValueNode locationIdentity) {
-        super(object, 0, offset, accessKind);
-        this.condition = condition;
-        this.locationIdentity = locationIdentity;
-    }
-
-    public ValueNode getCondition() {
-        return condition;
-    }
-
-    public ValueNode getLocationIdentity() {
-        return locationIdentity;
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        return this;
-    }
-
-    @Override
-    public void virtualize(VirtualizerTool tool) {
-        super.virtualize(tool);
-    }
-
-    @SuppressWarnings("unused")
-    public static <T> T load(Object object, long offset, @ConstantNodeParameter Kind kind, boolean condition, Object locationIdentity) {
-        return UnsafeLoadNode.load(object, 0, offset, kind);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java	Mon Oct 07 23:16:00 2013 +0200
@@ -0,0 +1,70 @@
+/*
+ * 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.truffle.nodes.typesystem;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.truffle.nodes.asserts.*;
+import com.oracle.truffle.api.*;
+
+/**
+ * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class, boolean)}.
+ */
+public class CustomizedUnsafeStoreMacroNode extends NeverPartOfCompilationNode implements Canonicalizable {
+
+    private static final int ARGUMENT_COUNT = 4;
+    private static final int OBJECT_ARGUMENT_INDEX = 0;
+    private static final int OFFSET_ARGUMENT_INDEX = 1;
+    private static final int VALUE_ARGUMENT_INDEX = 2;
+    private static final int LOCATION_ARGUMENT_INDEX = 3;
+
+    public CustomizedUnsafeStoreMacroNode(Invoke invoke) {
+        super(invoke, "The location argument could not be resolved to a constant.");
+        assert arguments.size() == ARGUMENT_COUNT;
+    }
+
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        ValueNode locationArgument = arguments.get(LOCATION_ARGUMENT_INDEX);
+        if (locationArgument.isConstant()) {
+            ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX);
+            ValueNode offsetArgument = arguments.get(OFFSET_ARGUMENT_INDEX);
+            ValueNode valueArgument = arguments.get(VALUE_ARGUMENT_INDEX);
+            Object locationIdentityObject = locationArgument.asConstant().asObject();
+            LocationIdentity locationIdentity;
+            if (locationIdentityObject == null) {
+                locationIdentity = LocationIdentity.ANY_LOCATION;
+            } else {
+                locationIdentity = ObjectLocationIdentity.create(locationIdentityObject);
+            }
+
+            UnsafeStoreNode unsafeStoreNode = graph().add(new UnsafeStoreNode(objectArgument, offsetArgument, valueArgument, valueArgument.kind(), locationIdentity));
+            unsafeStoreNode.setStateAfter(this.stateAfter());
+            return unsafeStoreNode;
+        }
+        return this;
+    }
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreNode.java	Mon Oct 07 14:47:18 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2012, 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.truffle.nodes.typesystem;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-
-public final class CustomizedUnsafeStoreNode extends UnsafeStoreNode {
-
-    @Input private ValueNode customLocationIdentity;
-
-    public CustomizedUnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, ValueNode customLocationIdentity) {
-        super(object, 0, offset, value, accessKind);
-        this.customLocationIdentity = customLocationIdentity;
-    }
-
-    public ValueNode getCustomLocationIdentity() {
-        return customLocationIdentity;
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        return this;
-    }
-
-    @Override
-    public void virtualize(VirtualizerTool tool) {
-        super.virtualize(tool);
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void store(Object object, long offset, Object value, @ConstantNodeParameter Kind kind, Object customLocationIdentity) {
-        UnsafeStoreNode.store(object, 0, offset, value, kind);
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void store(Object object, long offset, boolean value, @ConstantNodeParameter Kind kind, Object customLocationIdentity) {
-        UnsafeStoreNode.store(object, 0, offset, value, kind);
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void store(Object object, long offset, byte value, @ConstantNodeParameter Kind kind, Object customLocationIdentity) {
-        UnsafeStoreNode.store(object, 0, offset, value, kind);
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void store(Object object, long offset, char value, @ConstantNodeParameter Kind kind, Object customLocationIdentity) {
-        UnsafeStoreNode.store(object, 0, offset, value, kind);
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void store(Object object, long offset, double value, @ConstantNodeParameter Kind kind, Object customLocationIdentity) {
-        UnsafeStoreNode.store(object, 0, offset, value, kind);
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void store(Object object, long offset, float value, @ConstantNodeParameter Kind kind, Object customLocationIdentity) {
-        UnsafeStoreNode.store(object, 0, offset, value, kind);
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void store(Object object, long offset, int value, @ConstantNodeParameter Kind kind, Object customLocationIdentity) {
-        UnsafeStoreNode.store(object, 0, offset, value, kind);
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void store(Object object, long offset, long value, @ConstantNodeParameter Kind kind, Object customLocationIdentity) {
-        UnsafeStoreNode.store(object, 0, offset, value, kind);
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void store(Object object, long offset, short value, @ConstantNodeParameter Kind kind, Object customLocationIdentity) {
-        UnsafeStoreNode.store(object, 0, offset, value, kind);
-    }
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Mon Oct 07 23:16:00 2013 +0200
@@ -66,78 +66,48 @@
     @MacroSubstitution(macro = UnsafeTypeCastMacroNode.class, isStatic = true)
     public static native Object unsafeCast(Object value, Class clazz, boolean condition);
 
-    @MethodSubstitution
-    public static boolean unsafeGetBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return CustomizedUnsafeLoadNode.load(receiver, offset, Kind.Boolean, condition, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true)
+    public static native boolean unsafeGetBoolean(Object receiver, long offset, boolean condition, Object locationIdentity);
 
-    @MethodSubstitution
-    public static byte unsafeGetByte(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return CustomizedUnsafeLoadNode.load(receiver, offset, Kind.Byte, condition, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true)
+    public static native byte unsafeGetByte(Object receiver, long offset, boolean condition, Object locationIdentity);
 
-    @MethodSubstitution
-    public static short unsafeGetShort(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return CustomizedUnsafeLoadNode.load(receiver, offset, Kind.Short, condition, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true)
+    public static native short unsafeGetShort(Object receiver, long offset, boolean condition, Object locationIdentity);
 
-    @MethodSubstitution
-    public static int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return CustomizedUnsafeLoadNode.load(receiver, offset, Kind.Int, condition, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true)
+    public static native int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity);
 
-    @MethodSubstitution
-    public static float unsafeGetFloat(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return CustomizedUnsafeLoadNode.load(receiver, offset, Kind.Float, condition, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true)
+    public static native float unsafeGetFloat(Object receiver, long offset, boolean condition, Object locationIdentity);
 
-    @MethodSubstitution
-    public static double unsafeGetDouble(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return CustomizedUnsafeLoadNode.load(receiver, offset, Kind.Double, condition, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true)
+    public static native double unsafeGetDouble(Object receiver, long offset, boolean condition, Object locationIdentity);
 
-    @MethodSubstitution
-    public static Object unsafeGetObject(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return CustomizedUnsafeLoadNode.load(receiver, offset, Kind.Object, condition, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true)
+    public static native Object unsafeGetObject(Object receiver, long offset, boolean condition, Object locationIdentity);
 
-    @MethodSubstitution
-    public static void unsafePutBoolean(Object receiver, long offset, boolean value, Object locationIdentity) {
-        CustomizedUnsafeStoreNode.store(receiver, offset, value, Kind.Boolean, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true)
+    public static native void unsafePutBoolean(Object receiver, long offset, boolean value, Object locationIdentity);
 
-    @MethodSubstitution
-    public static void unsafePutByte(Object receiver, long offset, byte value, Object locationIdentity) {
-        CustomizedUnsafeStoreNode.store(receiver, offset, value, Kind.Byte, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true)
+    public static native void unsafePutByte(Object receiver, long offset, byte value, Object locationIdentity);
 
-    @MethodSubstitution
-    public static void unsafePutShort(Object receiver, long offset, short value, Object locationIdentity) {
-        CustomizedUnsafeStoreNode.store(receiver, offset, value, Kind.Short, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true)
+    public static native void unsafePutShort(Object receiver, long offset, short value, Object locationIdentity);
 
-    @MethodSubstitution
-    public static void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity) {
-        CustomizedUnsafeStoreNode.store(receiver, offset, value, Kind.Int, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true)
+    public static native void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity);
 
-    @MethodSubstitution
-    public static void unsafePutLong(Object receiver, long offset, long value, Object locationIdentity) {
-        CustomizedUnsafeStoreNode.store(receiver, offset, value, Kind.Long, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true)
+    public static native void unsafePutLong(Object receiver, long offset, long value, Object locationIdentity);
 
-    @MethodSubstitution
-    public static void unsafePutFloat(Object receiver, long offset, float value, Object locationIdentity) {
-        CustomizedUnsafeStoreNode.store(receiver, offset, value, Kind.Float, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true)
+    public static native void unsafePutFloat(Object receiver, long offset, float value, Object locationIdentity);
 
-    @MethodSubstitution
-    public static void unsafePutDouble(Object receiver, long offset, double value, Object locationIdentity) {
-        CustomizedUnsafeStoreNode.store(receiver, offset, value, Kind.Double, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true)
+    public static native void unsafePutDouble(Object receiver, long offset, double value, Object locationIdentity);
 
-    @MethodSubstitution
-    public static void unsafePutObject(Object receiver, long offset, Object value, Object locationIdentity) {
-        CustomizedUnsafeStoreNode.store(receiver, offset, value, Kind.Object, locationIdentity);
-    }
+    @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true)
+    public static native void unsafePutObject(Object receiver, long offset, Object value, Object locationIdentity);
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Mon Oct 07 23:16:00 2013 +0200
@@ -64,14 +64,14 @@
         public abstract boolean conflicts(LocationIdentity other);
     }
 
-    static class LoadCacheEntry extends CacheEntry<ResolvedJavaField> {
+    static class LoadCacheEntry extends CacheEntry<LocationIdentity> {
 
-        public LoadCacheEntry(ValueNode object, ResolvedJavaField identity) {
+        public LoadCacheEntry(ValueNode object, LocationIdentity identity) {
             super(object, identity);
         }
 
         @Override
-        public CacheEntry<ResolvedJavaField> duplicateWithObject(ValueNode newObject) {
+        public CacheEntry<LocationIdentity> duplicateWithObject(ValueNode newObject) {
             return new LoadCacheEntry(newObject, identity);
         }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Mon Oct 07 14:47:18 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Mon Oct 07 23:16:00 2013 +0200
@@ -81,7 +81,7 @@
                     effects.deleteFixedNode(store);
                     deleted = true;
                 }
-                state.killReadCache((LocationIdentity) store.field());
+                state.killReadCache(store.field());
                 state.addCacheEntry(identifier, value);
             } else {
                 processIdentity(state, ANY_LOCATION);
@@ -100,6 +100,20 @@
                     state.addCacheEntry(identifier, read);
                 }
             }
+        } else if (node instanceof UnsafeLoadNode) {
+            UnsafeLoadNode load = (UnsafeLoadNode) node;
+            if (load.offset().isConstant() && load.getLocationIdentity() != LocationIdentity.ANY_LOCATION) {
+                ValueNode object = GraphUtil.unproxify(load.object());
+                LoadCacheEntry identifier = new LoadCacheEntry(object, load.getLocationIdentity());
+                ValueNode cachedValue = state.getCacheEntry(identifier);
+                if (cachedValue != null) {
+                    effects.replaceAtUsages(load, cachedValue);
+                    addScalarAlias(load, cachedValue);
+                    deleted = true;
+                } else {
+                    state.addCacheEntry(identifier, load);
+                }
+            }
         } else if (node instanceof WriteNode) {
             WriteNode write = (WriteNode) node;
             if (write.location() instanceof ConstantLocationNode) {
@@ -117,6 +131,23 @@
             } else {
                 processIdentity(state, write.location().getLocationIdentity());
             }
+        } else if (node instanceof UnsafeStoreNode) {
+            UnsafeStoreNode write = (UnsafeStoreNode) node;
+            if (write.offset().isConstant() && write.getLocationIdentity() != LocationIdentity.ANY_LOCATION) {
+                ValueNode object = GraphUtil.unproxify(write.object());
+                LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity());
+                ValueNode cachedValue = state.getCacheEntry(identifier);
+
+                ValueNode value = getScalarAlias(write.value());
+                if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
+                    effects.deleteFixedNode(write);
+                    deleted = true;
+                }
+                processIdentity(state, write.getLocationIdentity());
+                state.addCacheEntry(identifier, value);
+            } else {
+                processIdentity(state, write.getLocationIdentity());
+            }
         } else if (node instanceof MemoryCheckpoint.Single) {
             LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity();
             processIdentity(state, identity);