changeset 3069:6202a6bb6726

Restructure memory lowering code.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Fri, 24 Jun 2011 14:21:12 +0200
parents ea778c37bdae
children 16043c211a98
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryMergeNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessMonitor.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryAccess.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryMergeNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryRead.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryWrite.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java
diffstat 18 files changed, 570 insertions(+), 221 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Thu Jun 23 16:40:53 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Fri Jun 24 14:21:12 2011 +0200
@@ -101,6 +101,7 @@
     public static boolean TraceAssembler                     = ____;
     public static boolean TraceInlining                      = ____;
     public static boolean TraceDeadCodeElimination           = ____;
+    public static boolean TraceMemoryMaps                    = ____;
     public static int     TraceBytecodeParserLevel           = 0;
     public static boolean QuietBailout                       = ____;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Thu Jun 23 16:40:53 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Fri Jun 24 14:21:12 2011 +0200
@@ -1372,7 +1372,9 @@
         }
 
         LIRGeneratorOp op = instr.lookup(LIRGeneratorOp.class);
-        op.generate(instr, this);
+        if (op != null) {
+            op.generate(instr, this);
+        }
 
         if (GraalOptions.TraceLIRVisit) {
             TTY.println("Operand for " + instr + " = " + instr.operand());
@@ -1443,14 +1445,14 @@
     }
 
     @Override
-    public void visitMemoryRead(MemoryRead memRead) {
-        lir.move(new CiAddress(memRead.valueKind(), load(memRead.location()), memRead.displacement()), createResultVariable(memRead), memRead.valueKind());
+    public void visitMemoryRead(ReadNode memRead) {
+        lir.move(memRead.location().createAddress(this, memRead.object()), createResultVariable(memRead), memRead.valueKind());
     }
 
 
     @Override
     public void visitMemoryWrite(MemoryWrite memWrite) {
-        lir.move(load(memWrite.value()), new CiAddress(memWrite.valueKind(), load(memWrite.location()), memWrite.displacement()), memWrite.valueKind());
+        lir.move(load(memWrite.value()), memWrite.location().createAddress(this, memWrite.object()), memWrite.valueKind());
     }
 
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java	Thu Jun 23 16:40:53 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java	Fri Jun 24 14:21:12 2011 +0200
@@ -51,7 +51,9 @@
         Phi phi = (Phi) x;
 
         if (phi.valueCount() == 1 && !cannotSimplify.isMarked(phi)) {
-            return (Value) phi.replace(phi.valueAt(0));
+            Value result = phi.valueAt(0);
+            phi.replace(result);
+            return result;
         }
 
         if (cannotSimplify.isMarked(phi)) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryMergeNode.java	Fri Jun 24 14:21:12 2011 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class AbstractMemoryMergeNode extends StateSplit {
+
+    private static final int SUCCESSOR_COUNT = 0;
+    private static final int INPUT_COUNT = 0;
+
+    public AbstractMemoryMergeNode(Graph graph) {
+        this(CiKind.Illegal, 0, 0, graph);
+    }
+
+    public AbstractMemoryMergeNode(CiKind result, int inputCount, int successorCount, Graph graph) {
+        super(result, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+
+    public List<Node> mergedNodes() {
+        return inputs().variablePart();
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessMonitor.java	Thu Jun 23 16:40:53 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessMonitor.java	Fri Jun 24 14:21:12 2011 +0200
@@ -28,7 +28,7 @@
 /**
  * The {@code AccessMonitor} instruction is the base class of both monitor acquisition and release.
  */
-public abstract class AccessMonitor extends StateSplit {
+public abstract class AccessMonitor extends AbstractMemoryMergeNode {
 
     private static final int INPUT_COUNT = 2;
     private static final int INPUT_OBJECT = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java	Fri Jun 24 14:21:12 2011 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class AccessNode extends StateSplit {
+    private static final int INPUT_COUNT = 3;
+    private static final int INPUT_NODE = 0;
+    private static final int INPUT_GUARD = 1;
+    private static final int INPUT_MEMORY_STATE = 2;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private LocationNode location;
+    private CiKind valueKind;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+    }
+
+    public Value setObject(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_NODE, n);
+    }
+
+    public GuardNode guard() {
+        return (GuardNode) inputs().get(super.inputCount() + INPUT_GUARD);
+    }
+
+    public void setGuard(GuardNode n) {
+        inputs().set(super.inputCount() + INPUT_GUARD, n);
+    }
+
+    public GuardNode memoryState() {
+        return (GuardNode) inputs().get(super.inputCount() + INPUT_MEMORY_STATE);
+    }
+
+    public void setMemoryState(GuardNode n) {
+        inputs().set(super.inputCount() + INPUT_MEMORY_STATE, n);
+    }
+
+    public LocationNode location() {
+        return location;
+    }
+
+    public CiKind valueKind() {
+        return valueKind;
+    }
+
+    public AccessNode(CiKind kind, Value object, LocationNode location, int inputCount, int successorCount, Graph graph) {
+        super(kind.stackKind(), INPUT_COUNT + inputCount, SUCCESSOR_COUNT + successorCount, graph);
+        this.location = location;
+        this.valueKind = kind;
+        setObject(object);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("mem read from ").print(object());
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Thu Jun 23 16:40:53 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Fri Jun 24 14:21:12 2011 +0200
@@ -34,7 +34,7 @@
 /**
  * The {@code Invoke} instruction represents all kinds of method calls.
  */
-public final class Invoke extends StateSplit implements ExceptionEdgeInstruction {
+public final class Invoke extends AbstractMemoryMergeNode implements ExceptionEdgeInstruction {
 
     private final int argumentCount;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java	Fri Jun 24 14:21:12 2011 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class LocationNode extends FloatingNode {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private int displacement;
+    private CiKind valueKind;
+    private Object identity;
+
+    public LocationNode(Object identity, CiKind kind, int displacement, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.displacement = displacement;
+        this.valueKind = kind;
+        this.identity = identity;
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("mem location disp is ").print(displacement);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new LocationNode(identity, valueKind, displacement, into);
+    }
+
+    public CiValue createAddress(LIRGenerator lirGenerator, Value object) {
+        return new CiAddress(valueKind, lirGenerator.load(object), displacement);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryAccess.java	Thu Jun 23 16:40:53 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.ir;
-
-import com.oracle.max.graal.compiler.debug.*;
-import com.oracle.max.graal.graph.*;
-import com.sun.cri.ci.*;
-
-
-public abstract class MemoryAccess extends StateSplit {
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_NODE = 0;
-    private static final int INPUT_GUARD = 1;
-
-    private static final int SUCCESSOR_COUNT = 0;
-
-    private int displacement;
-    private CiKind valueKind;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
-
-    /**
-     * The instruction that produces the object tested against null.
-     */
-     public Value location() {
-        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
-    }
-
-    public Value setLocation(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_NODE, n);
-    }
-
-    /**
-     * The instruction that produces the object tested against null.
-     */
-     public GuardNode guard() {
-        return (GuardNode) inputs().get(super.inputCount() + INPUT_GUARD);
-    }
-
-    public void setGuard(GuardNode n) {
-        inputs().set(super.inputCount() + INPUT_GUARD, n);
-    }
-
-    public int displacement() {
-        return displacement;
-    }
-
-    public CiKind valueKind() {
-        return valueKind;
-    }
-
-    public MemoryAccess(CiKind kind, Value location, int displacement, int inputCount, int successorCount, Graph graph) {
-        super(kind.stackKind(), INPUT_COUNT + inputCount, SUCCESSOR_COUNT + successorCount, graph);
-        this.displacement = displacement;
-        this.valueKind = kind;
-        setLocation(location);
-    }
-
-    @Override
-    public void print(LogStream out) {
-        out.print("mem read from ").print(location());
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryMergeNode.java	Fri Jun 24 14:21:12 2011 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class MemoryMergeNode extends AbstractMemoryMergeNode {
+
+    private static final int SUCCESSOR_COUNT = 0;
+    private static final int INPUT_COUNT = 0;
+
+    public MemoryMergeNode(Graph graph) {
+        this(CiKind.Illegal, 0, 0, graph);
+    }
+
+    public MemoryMergeNode(CiKind result, int inputCount, int successorCount, Graph graph) {
+        super(result, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new MemoryMergeNode(into);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryRead.java	Thu Jun 23 16:40:53 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.ir;
-
-import com.oracle.max.graal.compiler.debug.*;
-import com.oracle.max.graal.graph.*;
-import com.sun.cri.ci.*;
-
-
-public final class MemoryRead extends MemoryAccess {
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
-
-    public MemoryRead(CiKind kind, Value location, int displacement, Graph graph) {
-        super(kind, location, displacement, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-    }
-
-    @Override
-    public void accept(ValueVisitor v) {
-        v.visitMemoryRead(this);
-    }
-
-    @Override
-    public void print(LogStream out) {
-        out.print("mem read from ").print(location());
-    }
-
-    @Override
-    public Node copy(Graph into) {
-        return new MemoryRead(super.kind, null, displacement(), into);
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryWrite.java	Thu Jun 23 16:40:53 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryWrite.java	Fri Jun 24 14:21:12 2011 +0200
@@ -25,9 +25,10 @@
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
 
 
-public final class MemoryWrite extends MemoryAccess {
+public final class MemoryWrite extends AccessNode {
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_VALUE = 0;
     private static final int SUCCESSOR_COUNT = 0;
@@ -45,8 +46,8 @@
         inputs().set(super.inputCount() + INPUT_VALUE, v);
     }
 
-    public MemoryWrite(CiKind kind, Value object, Value value, int displacement, Graph graph) {
-        super(kind, object, displacement, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    public MemoryWrite(CiKind kind, Value object, Value value, LocationNode location, Graph graph) {
+        super(kind, object, location, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         setValue(value);
     }
 
@@ -57,11 +58,11 @@
 
     @Override
     public void print(LogStream out) {
-        out.print("mem write to ").print(location()).print(" with value").print(value());
+        out.print("mem write to ").print(object()).print(" with value").print(value());
     }
 
     @Override
     public Node copy(Graph into) {
-        return new MemoryWrite(super.kind, null, null, displacement(), into);
+        return new MemoryWrite(super.kind, null, null, null, into);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadNode.java	Fri Jun 24 14:21:12 2011 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class ReadNode extends AccessNode {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+
+    public ReadNode(CiKind kind, Value object, LocationNode location, Graph graph) {
+        super(kind, object, location, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMemoryRead(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("mem read from ").print(object());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new ReadNode(super.kind, null, null, into);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Thu Jun 23 16:40:53 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Fri Jun 24 14:21:12 2011 +0200
@@ -157,7 +157,9 @@
         throw new IllegalStateException("No visit method for this node");
     }
 
-    public abstract void print(LogStream out);
+    public void print(LogStream out) {
+        out.print(this.getClass().toString());
+    }
 
     @SuppressWarnings("unchecked")
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java	Thu Jun 23 16:40:53 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java	Fri Jun 24 14:21:12 2011 +0200
@@ -51,7 +51,7 @@
     public abstract void visitLocal(Local i);
     public abstract void visitLogic(Logic i);
     public abstract void visitLookupSwitch(LookupSwitch i);
-    public abstract void visitMemoryRead(MemoryRead i);
+    public abstract void visitMemoryRead(ReadNode i);
     public abstract void visitMemoryWrite(MemoryWrite i);
     public abstract void visitMonitorAddress(MonitorAddress monitorAddress);
     public abstract void visitMonitorEnter(MonitorEnter i);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Thu Jun 23 16:40:53 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Fri Jun 24 14:21:12 2011 +0200
@@ -22,6 +22,11 @@
  */
 package com.oracle.max.graal.compiler.phases;
 
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.graph.*;
@@ -32,84 +37,201 @@
 
     public static final LoweringOp DELEGATE_TO_RUNTIME = new LoweringOp() {
         @Override
-        public Node lower(Node n, CiLoweringTool tool) {
-            return tool.getRuntime().lower(n, tool);
+        public void lower(Node n, CiLoweringTool tool) {
+            tool.getRuntime().lower(n, tool);
         }
     };
 
     private final RiRuntime runtime;
+    private Graph currentGraph;
 
     public LoweringPhase(RiRuntime runtime) {
         this.runtime = runtime;
     }
 
+    public static class MemoryMap {
+
+        private final Block block;
+        private HashMap<Object, Node> locationToWrite;
+        private HashMap<Object, List<Node>> locationToReads;
+
+        public MemoryMap(Block b, MemoryMap memoryMap) {
+            this(b);
+        }
+
+        public MemoryMap(Block b) {
+            block = b;
+            locationToWrite = new HashMap<Object, Node>();
+            locationToReads = new HashMap<Object, List<Node>>();
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Creating new memory map for block B" + b.blockID());
+            }
+        }
+
+        public void mergeWith(MemoryMap memoryMap) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Merging with memory map of block B" + memoryMap.block.blockID());
+            }
+        }
+
+        public void createMemoryMerge(AbstractMemoryMergeNode memMerge) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Creating memory merge at node " + memMerge.id());
+            }
+
+            for (Entry<Object, Node> writeEntry : locationToWrite.entrySet()) {
+                memMerge.mergedNodes().add(writeEntry.getValue());
+            }
+
+            TTY.println("entrySet size" + locationToReads.entrySet());
+            for (Entry<Object, List<Node>> readEntry : locationToReads.entrySet()) {
+                TTY.println(readEntry.getValue().toString());
+                memMerge.mergedNodes().addAll(readEntry.getValue());
+            }
+
+            locationToReads.clear();
+            locationToWrite.clear();
+        }
+
+        public void registerWrite(Object location, Node node) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Register write to " + location + " at node " + node.id());
+            }
+
+            if (locationToWrite.containsKey(location)) {
+                Node prevWrite = locationToWrite.get(location);
+                node.inputs().add(prevWrite);
+            }
+
+            if (locationToReads.containsKey(location)) {
+                for (Node prevRead : locationToReads.get(location)) {
+                    node.inputs().add(prevRead);
+                }
+            }
+            locationToWrite.put(location, node);
+            locationToReads.remove(location);
+        }
+
+        public void registerRead(Object location, Node node) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Register read to " + location + " at node " + node.id());
+            }
+
+            if (locationToWrite.containsKey(location)) {
+                Node prevWrite = locationToWrite.get(location);
+                node.inputs().add(prevWrite);
+            }
+
+            if (!locationToReads.containsKey(location)) {
+                locationToReads.put(location, new ArrayList<Node>());
+            }
+            locationToReads.get(location).add(node);
+            TTY.println("entrySet size" + locationToReads.entrySet());
+        }
+
+        public Node getMemoryState(Object location) {
+            return null;
+        }
+    }
+
     @Override
     protected void run(final Graph graph) {
+        this.currentGraph = graph;
         final IdentifyBlocksPhase s = new IdentifyBlocksPhase(false);
         s.apply(graph);
 
-        for (Block b : s.getBlocks()) {
-            final Node[] firstNodeValue = new Node[]{b.firstNode()};
+        List<Block> blocks = s.getBlocks();
+        MemoryMap[] memoryMaps = new MemoryMap[blocks.size()];
+        for (final Block b : blocks) {
+            process(b, memoryMaps);
+        }
+    }
+
+    private void process(final Block b, MemoryMap[] memoryMaps) {
+        // Visit every block at most once.
+        if (memoryMaps[b.blockID()] != null) {
+            return;
+        }
+
+        // Process predecessors before this block.
+        for (Block pred : b.getPredecessors()) {
+            process(pred, memoryMaps);
+        }
 
-            final CiLoweringTool loweringTool = new CiLoweringTool() {
-                @Override
-                public Node getGuardAnchor() {
-                    Node firstNode = firstNodeValue[0];
-                    if (firstNode == firstNode.graph().start()) {
-                        Anchor a = new Anchor(graph);
-                        a.setNext((FixedNode) firstNode.graph().start().start());
-                        firstNode.graph().start().setStart(a);
-                        firstNodeValue[0] = a;
-                        return a;
-                    } else if (firstNode instanceof Merge) {
-                        Merge merge = (Merge) firstNode;
-                        Anchor a = new Anchor(graph);
-                        a.setNext(merge.next());
-                        merge.setNext(a);
-                        firstNodeValue[0] = a;
-                        return a;
-                    } else if (!(firstNode instanceof Anchor)) {
-                        Anchor a = new Anchor(graph);
-                        assert firstNode.predecessors().size() == 1 : firstNode;
-                        Node pred = firstNode.predecessors().get(0);
-                        int predIndex = pred.successors().indexOf(firstNode);
-                        pred.successors().set(predIndex, a);
-                        a.setNext((FixedNode) firstNode);
-                        firstNodeValue[0] = a;
-                        return a;
+        // Create initial memory map for the block.
+        MemoryMap map = null;
+        if (b.getPredecessors().size() == 0) {
+            map = new MemoryMap(b);
+        } else {
+            map = new MemoryMap(b, memoryMaps[b.getPredecessors().get(0).blockID()]);
+            for (int i=1; i<b.getPredecessors().size(); ++i) {
+                map.mergeWith(memoryMaps[b.getPredecessors().get(0).blockID()]);
+            }
+        }
+        final MemoryMap finalMap = map;
+        memoryMaps[b.blockID()] = finalMap;
+
+        final CiLoweringTool loweringTool = new CiLoweringTool() {
+
+            @Override
+            public Node getGuardAnchor() {
+                return b.createAnchor();
+            }
+
+            @Override
+            public RiRuntime getRuntime() {
+                return runtime;
+            }
+
+            @Override
+            public Node createGuard(Node condition) {
+                Anchor anchor = (Anchor) getGuardAnchor();
+                for (GuardNode guard : anchor.happensAfterGuards()) {
+                    if (guard.node().valueEqual(condition)) {
+                        condition.delete();
+                        return guard;
                     }
-                    return firstNode;
                 }
+                GuardNode newGuard = new GuardNode(currentGraph);
+                newGuard.setAnchor(anchor);
+                newGuard.setNode((BooleanNode) condition);
+                return newGuard;
+            }
 
-                @Override
-                public RiRuntime getRuntime() {
-                    return runtime;
-                }
+            @Override
+            public void createMemoryMerge(Node node) {
+                assert node instanceof AbstractMemoryMergeNode;
+                AbstractMemoryMergeNode memMerge = (AbstractMemoryMergeNode) node;
+                assert memMerge.mergedNodes().size() == 0;
+                finalMap.createMemoryMerge(memMerge);
+            }
+
+            @Override
+            public void registerRead(Object location, Node node) {
+                finalMap.registerRead(location, node);
+            }
 
-                @Override
-                public Node createGuard(Node condition) {
-                    Anchor anchor = (Anchor) getGuardAnchor();
-                    for (GuardNode guard : anchor.happensAfterGuards()) {
-                        if (guard.node().valueEqual(condition)) {
-                            condition.delete();
-                            return guard;
-                        }
-                    }
-                    GuardNode newGuard = new GuardNode(graph);
-                    newGuard.setAnchor(anchor);
-                    newGuard.setNode((BooleanNode) condition);
-                    return newGuard;
-                }
-            };
+            @Override
+            public void registerWrite(Object location, Node node) {
+                finalMap.registerWrite(location, node);
+            }
+
+            @Override
+            public Node getMemoryState(Object location) {
+                return finalMap.getMemoryState(location);
+            }
+        };
 
-            for (final Node n : b.getInstructions()) {
-                if (n instanceof FixedNode) {
-                    LoweringOp op = n.lookup(LoweringOp.class);
-                    if (op != null) {
-                        Node newNode = op.lower(n, loweringTool);
-                        if (newNode != null) {
-                            n.replace(newNode);
-                        }
+        // Lower the instructions of this block.
+        for (final Node n : b.getInstructions()) {
+            if (n instanceof FixedNode) {
+                LoweringOp op = n.lookup(LoweringOp.class);
+                if (op != null) {
+                    op.lower(n, loweringTool);
+                } else {
+                    // This memory merge node is not lowered => create a memory merge nevertheless.
+                    if (n instanceof AbstractMemoryMergeNode) {
+                        loweringTool.createMemoryMerge(n);
                     }
                 }
             }
@@ -117,6 +239,6 @@
     }
 
     public interface LoweringOp extends Op {
-        Node lower(Node n, CiLoweringTool tool);
+        void lower(Node n, CiLoweringTool tool);
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Thu Jun 23 16:40:53 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Fri Jun 24 14:21:12 2011 +0200
@@ -37,6 +37,7 @@
     private Block dominator;
     private Block javaBlock;
     private final List<Block> dominators = new ArrayList<Block>();
+    private Anchor anchor;
 
     private Node firstNode;
     private Node lastNode;
@@ -47,6 +48,7 @@
 
     public void setFirstNode(Node node) {
         this.firstNode = node;
+        this.anchor = null;
     }
 
     public Block javaBlock() {
@@ -61,6 +63,44 @@
         return lastNode;
     }
 
+    public Anchor createAnchor() {
+        if (anchor == null) {
+            if (firstNode instanceof Anchor) {
+                this.anchor = (Anchor) firstNode;
+            } else if (firstNode == firstNode.graph().start()) {
+                StartNode start = (StartNode) firstNode;
+                if (start.start() instanceof Anchor) {
+                    this.anchor = (Anchor) start.start();
+                } else {
+                    Anchor a = new Anchor(firstNode.graph());
+                    a.setNext((FixedNode) firstNode.graph().start().start());
+                    firstNode.graph().start().setStart(a);
+                    this.anchor = a;
+                }
+            } else if (firstNode instanceof Merge) {
+                Merge merge = (Merge) firstNode;
+                if (merge.next() instanceof Anchor) {
+                    this.anchor = (Anchor) merge.next();
+                } else {
+                    Anchor a = new Anchor(firstNode.graph());
+                    a.setNext(merge.next());
+                    merge.setNext(a);
+                    this.anchor = a;
+                }
+            } else {
+                assert !(firstNode instanceof Anchor);
+                Anchor a = new Anchor(firstNode.graph());
+                assert firstNode.predecessors().size() == 1 : firstNode;
+                Node pred = firstNode.predecessors().get(0);
+                int predIndex = pred.successors().indexOf(firstNode);
+                pred.successors().set(predIndex, a);
+                a.setNext((FixedNode) firstNode);
+                this.anchor = a;
+            }
+        }
+        return anchor;
+    }
+
     public void setLastNode(Node node) {
         this.lastNode = node;
     }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Thu Jun 23 16:40:53 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Fri Jun 24 14:21:12 2011 +0200
@@ -242,29 +242,34 @@
     }
 
     @Override
-    public Node lower(Node n, CiLoweringTool tool) {
+    public void lower(Node n, CiLoweringTool tool) {
         if (n instanceof LoadField) {
             LoadField field = (LoadField) n;
             if (field.isVolatile()) {
-                return null;
+                return;
             }
             Graph graph = field.graph();
             int displacement = ((HotSpotField) field.field()).offset();
             assert field.kind != CiKind.Illegal;
-            MemoryRead memoryRead = new MemoryRead(field.field().kind(), field.object(), displacement, graph);
+            ReadNode memoryRead = new ReadNode(field.field().kind(), field.object(), new LocationNode(field.field(), field.field().kind(), displacement, graph), graph);
             memoryRead.setGuard((GuardNode) tool.createGuard(new IsNonNull(field.object(), graph)));
             memoryRead.setNext(field.next());
-            return memoryRead;
+            field.replace(memoryRead);
         } else if (n instanceof StoreField) {
             StoreField field = (StoreField) n;
             if (field.isVolatile()) {
-                return null;
+                return;
             }
             Graph graph = field.graph();
             int displacement = ((HotSpotField) field.field()).offset();
-            MemoryWrite memoryWrite = new MemoryWrite(field.field().kind(), field.object(), field.value(), displacement, graph);
+            MemoryWrite memoryWrite = new MemoryWrite(field.field().kind(), field.object(), field.value(), new LocationNode(field.field(), field.field().kind(), displacement, graph), graph);
+            memoryWrite.setGuard((GuardNode) tool.createGuard(new IsNonNull(field.object(), graph)));
             memoryWrite.setStateAfter(field.stateAfter());
-            memoryWrite.setGuard((GuardNode) tool.createGuard(new IsNonNull(field.object(), graph)));
+            memoryWrite.setNext(field.next());
+
+            //MemoryMergeNode memoryMergeNode = new MemoryMergeNode(graph);
+            //memoryMergeNode.setStateAfter(field.stateAfter());
+            //tool.createMemoryMerge(memoryMergeNode);
             if (field.field().kind() == CiKind.Object && !field.value().isNullConstant()) {
                 FieldWriteBarrier writeBarrier = new FieldWriteBarrier(field.object(), graph);
                 memoryWrite.setNext(writeBarrier);
@@ -272,8 +277,7 @@
             } else {
                 memoryWrite.setNext(field.next());
             }
-            return memoryWrite;
+            field.replace(memoryWrite);
         }
-        return null;
     }
 }