changeset 16300:8da760bd1575

Merge.
author Doug Simon <doug.simon@oracle.com>
date Mon, 30 Jun 2014 17:28:53 +0200
parents 732a9e80e8dc (diff) 81e4af185dd6 (current diff)
children b741f44cb277 281c30cf1952
files
diffstat 13 files changed, 124 insertions(+), 288 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Mon Jun 30 16:14:00 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Mon Jun 30 17:28:53 2014 +0200
@@ -90,7 +90,7 @@
      * Determines if verification is enabled in the current method, regardless of the
      * {@linkplain Debug#currentScope() current debug scope}.
      *
-     * @see Debug#verify(Object, Object)
+     * @see Debug#verify(Object, String)
      */
     public static boolean isVerifyEnabledForMethod() {
         if (!ENABLED) {
@@ -107,7 +107,7 @@
      * Determines if verification is enabled in the {@linkplain Debug#currentScope() current debug
      * scope}.
      *
-     * @see Debug#verify(Object, Object)
+     * @see Debug#verify(Object, String)
      */
     public static boolean isVerifyEnabled() {
         return ENABLED && DebugScope.getInstance().isVerifyEnabled();
@@ -491,13 +491,13 @@
      * config} to perform verification on a given object.
      *
      * @param object object to verify
-     * @param context object describing the context of verification
+     * @param message description of verification context
      *
-     * @see DebugVerifyHandler#verify(Object, Object...)
+     * @see DebugVerifyHandler#verify(Object, String)
      */
-    public static void verify(Object object, Object context) {
+    public static void verify(Object object, String message) {
         if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) {
-            DebugScope.getInstance().verify(object, context);
+            DebugScope.getInstance().verify(object, message);
         }
     }
 
@@ -506,28 +506,28 @@
      * config} to perform verification on a given object.
      *
      * @param object object to verify
-     * @param context1 first object describing the context of verification
-     * @param context2 second object describing the context of verification
+     * @param format a format string for the description of the verification context
+     * @param arg the argument referenced by the format specifiers in {@code format}
      *
-     * @see DebugVerifyHandler#verify(Object, Object...)
+     * @see DebugVerifyHandler#verify(Object, String)
      */
-    public static void verify(Object object, Object context1, Object context2) {
+    public static void verify(Object object, String format, Object arg) {
         if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) {
-            DebugScope.getInstance().verify(object, context1, context2);
+            DebugScope.getInstance().verify(object, format, arg);
         }
     }
 
     /**
-     * This override exists to catch cases when {@link #verify(Object, Object)} is called with one
-     * argument bound to a varargs method parameter. It will bind to this method instead of the
-     * single arg variant and produce a deprecation warning instead of silently wrapping the
+     * This override exists to catch cases when {@link #verify(Object, String, Object)} is called
+     * with one argument bound to a varargs method parameter. It will bind to this method instead of
+     * the single arg variant and produce a deprecation warning instead of silently wrapping the
      * Object[] inside of another Object[].
      */
     @Deprecated
-    public static void verify(Object object, Object[] args) {
+    public static void verify(Object object, String format, Object[] args) {
         assert false : "shouldn't use this";
         if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) {
-            DebugScope.getInstance().verify(object, args);
+            DebugScope.getInstance().verify(object, format, args);
         }
     }
 
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugVerifyHandler.java	Mon Jun 30 16:14:00 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugVerifyHandler.java	Mon Jun 30 17:28:53 2014 +0200
@@ -31,25 +31,7 @@
      * Verifies that a given object satisfies some invariants.
      *
      * @param object object to verify
-     * @param context object(s) describing the context of verification
-     */
-    void verify(Object object, Object... context);
-
-    /**
-     * Extracts the first object of a given type from a verification input object.
+     * @param message description of verification context
      */
-    default <T> T extract(Class<T> type, Object input) {
-        if (type.isInstance(input)) {
-            return type.cast(input);
-        }
-        if (input instanceof Object[]) {
-            for (Object nestedContext : (Object[]) input) {
-                T object = extract(type, nestedContext);
-                if (object != null) {
-                    return object;
-                }
-            }
-        }
-        return null;
-    }
+    void verify(Object object, String message);
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Mon Jun 30 16:14:00 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Mon Jun 30 17:28:53 2014 +0200
@@ -218,14 +218,15 @@
     }
 
     /**
-     * @see Debug#verify(Object, Object)
+     * @see Debug#verify(Object, String)
      */
-    public void verify(Object object, Object... ctx) {
+    public void verify(Object object, String formatString, Object... args) {
         if (isVerifyEnabled()) {
             DebugConfig config = getConfig();
             if (config != null) {
+                String message = String.format(formatString, args);
                 for (DebugVerifyHandler handler : config.verifyHandlers()) {
-                    handler.verify(object, ctx);
+                    handler.verify(object, message);
                 }
             }
         }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Jun 30 16:14:00 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Jun 30 17:28:53 2014 +0200
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.GraphEvent.NodeEvent;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.NodeClass.Position;
@@ -39,8 +38,6 @@
 
     public final String name;
 
-    private static final boolean TIME_TRAVEL = false;
-
     /**
      * The set of nodes in the graph, ordered by {@linkplain #register(Node) registration} time.
      */
@@ -67,7 +64,6 @@
     private final ArrayList<Node> nodeCacheLast;
     private int nodesDeletedSinceLastCompression;
     private int nodesDeletedBeforeLastCompression;
-    private GraphEventLog eventLog;
 
     /**
      * The number of times this graph has been compressed.
@@ -302,16 +298,46 @@
     }
 
     /**
+     * The type of events sent to a {@link NodeEventListener}.
+     */
+    public enum NodeEvent {
+        /**
+         * A node's input is changed.
+         */
+        INPUT_CHANGED,
+
+        /**
+         * A node's {@linkplain Node#usages() usages} count dropped to zero.
+         */
+        ZERO_USAGES,
+
+        /**
+         * A node was added to a graph.
+         */
+        NODE_ADDED;
+    }
+
+    /**
      * Client interested in one or more node related events.
      */
     public interface NodeEventListener {
 
         /**
+         * Default handler for events.
+         *
+         * @param e an event
+         * @param node the node related to {@code e}
+         */
+        default void event(NodeEvent e, Node node) {
+        }
+
+        /**
          * Notifies this listener of a change in a node's inputs.
          *
          * @param node a node who has had one of its inputs changed
          */
         default void inputChanged(Node node) {
+            event(NodeEvent.INPUT_CHANGED, node);
         }
 
         /**
@@ -320,6 +346,7 @@
          * @param node a node whose {@link Node#usages()} just became empty
          */
         default void usagesDroppedToZero(Node node) {
+            event(NodeEvent.ZERO_USAGES, node);
         }
 
         /**
@@ -328,6 +355,7 @@
          * @param node a node that was just added to the graph
          */
         default void nodeAdded(Node node) {
+            event(NodeEvent.NODE_ADDED, node);
         }
     }
 
@@ -375,8 +403,8 @@
         }
 
         public void usagesDroppedToZero(Node node) {
-            head.inputChanged(node);
-            next.inputChanged(node);
+            head.usagesDroppedToZero(node);
+            next.usagesDroppedToZero(node);
         }
     }
 
@@ -851,36 +879,11 @@
         if (nodeEventListener != null) {
             nodeEventListener.nodeAdded(node);
         }
-        logNodeAdded(node);
-    }
-
-    void logNodeAdded(Node node) {
-        if (TIME_TRAVEL) {
-            log(new GraphEvent.NodeEvent(node, GraphEvent.NodeEvent.Type.ADDED));
-        }
-    }
-
-    void logNodeDeleted(Node node) {
-        if (TIME_TRAVEL) {
-            log(new GraphEvent.NodeEvent(node, GraphEvent.NodeEvent.Type.DELETED));
-        }
-    }
-
-    private void log(NodeEvent nodeEvent) {
-        if (eventLog == null) {
-            eventLog = new GraphEventLog();
-        }
-        eventLog.add(nodeEvent);
-    }
-
-    public GraphEventLog getEventLog() {
-        return eventLog;
     }
 
     void unregister(Node node) {
         assert !isFrozen();
         assert !node.isDeleted() : "cannot delete a node twice! node=" + node;
-        logNodeDeleted(node);
         nodes[node.id] = null;
         nodesDeletedSinceLastCompression++;
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEvent.java	Mon Jun 30 16:14:00 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.graph;
-
-import java.io.*;
-
-public abstract class GraphEvent {
-
-    private Exception exceptionContext;
-
-    public static class NodeEvent extends GraphEvent {
-
-        public static enum Type {
-            ADDED,
-            DELETED,
-            CHANGED
-        }
-
-        public final Node node;
-        public final Type type;
-        private final String nodeString;
-
-        public NodeEvent(Node n, Type type) {
-            this.node = n;
-            this.type = type;
-            nodeString = n.toString();
-        }
-
-        @Override
-        public StackTraceElement[] print(StackTraceElement[] last, PrintStream stream) {
-            stream.println(type.toString() + ", " + nodeString);
-            return super.print(last, stream);
-        }
-    }
-
-    public static class EdgeEvent extends GraphEvent {
-
-        public static enum Type {
-            INPUT,
-            SUCC
-        }
-
-        public final Node node;
-        public final int index;
-        public final Node newValue;
-        public final Type type;
-
-        public EdgeEvent(Node node, int index, Node newValue, Type type) {
-            this.node = node;
-            this.index = index;
-            this.newValue = newValue;
-            this.type = type;
-        }
-    }
-
-    public GraphEvent() {
-        exceptionContext = new Exception();
-    }
-
-    public StackTraceElement[] print(StackTraceElement[] last, PrintStream stream) {
-        StackTraceElement[] stackTrace = exceptionContext.getStackTrace();
-
-        boolean atTop = true;
-        for (int i = 0; i < stackTrace.length; ++i) {
-            StackTraceElement elem = stackTrace[i];
-            int toBottom = stackTrace.length - i;
-            if (atTop) {
-                if (!elem.getClassName().startsWith("com.oracle.graal.graph.Graph") && !elem.getClassName().startsWith("com.oracle.graal.graph.Node")) {
-                    atTop = false;
-                } else {
-                    continue;
-                }
-            } else {
-                if (last.length >= toBottom && last[last.length - toBottom].equals(elem)) {
-                    continue;
-                }
-            }
-            stream.println(String.format("%s.%s(%s:%d)", elem.getClassName(), elem.getMethodName(), elem.getFileName(), elem.getLineNumber()));
-        }
-        return stackTrace;
-    }
-}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEventLog.java	Mon Jun 30 16:14:00 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.graph;
-
-import java.io.*;
-import java.util.*;
-
-public class GraphEventLog {
-
-    private List<GraphEvent> events = new ArrayList<>();
-
-    public void add(GraphEvent e) {
-        this.events.add(e);
-    }
-
-    public void printEvents(PrintStream stream) {
-        StackTraceElement[] last = new StackTraceElement[0];
-        for (GraphEvent e : events) {
-            last = e.print(last, stream);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Mon Jun 30 16:14:00 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Mon Jun 30 17:28:53 2014 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.graph.Graph.NodeEvent.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.*;
@@ -44,7 +46,7 @@
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
         ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(context.getMetaAccess());
-        HashSetNodeEventListener listener = new HashSetNodeEventListener.ExceptForAddedNodes();
+        HashSetNodeEventListener listener = new HashSetNodeEventListener().exclude(NODE_ADDED);
         int count = 0;
         while (true) {
             try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/IterativeFlowSensitiveReductionPhase.java	Mon Jun 30 16:14:00 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/IterativeFlowSensitiveReductionPhase.java	Mon Jun 30 17:28:53 2014 +0200
@@ -22,13 +22,15 @@
  */
 package com.oracle.graal.phases.common.cfs;
 
+import static com.oracle.graal.graph.Graph.NodeEvent.*;
+
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.Graph.NodeEventScope;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.CanonicalizerPhase;
+import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.common.util.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -47,7 +49,7 @@
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
         FlowSensitiveReductionPhase eliminate = new FlowSensitiveReductionPhase(context.getMetaAccess());
-        HashSetNodeEventListener listener = new HashSetNodeEventListener.ExceptForAddedNodes();
+        HashSetNodeEventListener listener = new HashSetNodeEventListener().exclude(NODE_ADDED);
         int count = 1;
         while (true) {
             try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/util/HashSetNodeEventListener.java	Mon Jun 30 16:14:00 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/util/HashSetNodeEventListener.java	Mon Jun 30 17:28:53 2014 +0200
@@ -24,7 +24,7 @@
 
 import java.util.*;
 
-import com.oracle.graal.graph.Graph.NodeEventListener;
+import com.oracle.graal.graph.Graph.*;
 import com.oracle.graal.graph.*;
 
 /**
@@ -33,36 +33,42 @@
  */
 public class HashSetNodeEventListener implements NodeEventListener {
 
+    private final Set<Node> nodes;
+    private final Set<NodeEvent> filter;
+
     /**
-     * Accumulates all node events except for {@link NodeEventListener#nodeAdded(Node) node
-     * additions}.
+     * Creates a {@link NodeEventListener} that collects nodes from all events.
+     */
+    public HashSetNodeEventListener() {
+        this.nodes = new HashSet<>();
+        this.filter = EnumSet.allOf(NodeEvent.class);
+    }
+
+    /**
+     * Creates a {@link NodeEventListener} that collects nodes from all events that match a given
+     * filter.
      */
-    public static class ExceptForAddedNodes extends HashSetNodeEventListener {
-        @Override
-        public void nodeAdded(Node node) {
+    public HashSetNodeEventListener(Set<NodeEvent> filter) {
+        this.nodes = new HashSet<>();
+        this.filter = filter;
+    }
+
+    /**
+     * Excludes a given event from those for which nodes are collected.
+     */
+    public HashSetNodeEventListener exclude(NodeEvent e) {
+        filter.remove(e);
+        return this;
+    }
+
+    public void event(NodeEvent e, Node node) {
+        if (filter.contains(e)) {
+            nodes.add(node);
         }
     }
 
-    private final Set<Node> nodes;
-
-    public HashSetNodeEventListener() {
-        this.nodes = new HashSet<>();
-    }
-
-    public void nodeAdded(Node node) {
-        nodes.add(node);
-    }
-
-    public void inputChanged(Node node) {
-        nodes.add(node);
-    }
-
-    public void usagesDroppedToZero(Node node) {
-        nodes.add(node);
-    }
-
     /**
-     * Gets the set of nodes that were communicated to this listener.
+     * Gets the set being used to accumulate the nodes communicated to this listener.
      */
     public Set<Node> getNodes() {
         return nodes;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Mon Jun 30 16:14:00 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Mon Jun 30 17:28:53 2014 +0200
@@ -101,7 +101,7 @@
                 Debug.dump(graph, "After phase %s", getName());
             }
             if (Debug.isVerifyEnabled()) {
-                Debug.verify(graph, this, "After phase " + getName());
+                Debug.verify(graph, "After phase %s", getName());
             }
             assert graph.verify();
         } catch (Throwable t) {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/NoDeadCodeVerifyHandler.java	Mon Jun 30 16:14:00 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/NoDeadCodeVerifyHandler.java	Mon Jun 30 17:28:53 2014 +0200
@@ -25,14 +25,12 @@
 import static com.oracle.graal.printer.NoDeadCodeVerifyHandler.Options.*;
 
 import java.util.*;
-import java.util.concurrent.*;
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.options.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 
 /**
@@ -54,34 +52,24 @@
         // @formatter:on
     }
 
-    private static final Map<Class<?>, Boolean> discovered = new ConcurrentHashMap<>();
-
-    public void verify(Object object, Object... context) {
-        if (NDCV.getValue() != OFF) {
-            StructuredGraph graph = extract(StructuredGraph.class, object);
-            BasePhase<?> phase = extract(BasePhase.class, context);
-            assert phase != null : "a Phase context is required by " + getClass().getSimpleName();
-            if (graph != null) {
-                List<Node> before = graph.getNodes().snapshot();
-                new DeadCodeEliminationPhase().run(graph);
-                List<Node> after = graph.getNodes().snapshot();
-                assert after.size() <= before.size();
-                if (before.size() != after.size()) {
-                    before.removeAll(after);
-                    if (discovered.put(phase.getClass(), Boolean.TRUE) == null) {
-                        String message = extract(String.class, context);
-                        String prefix = message == null ? "" : message + ": ";
-                        String phaseClass = phase.getClass().getName();
-                        GraalInternalError error = new GraalInternalError("%sfound dead nodes in %s (phase class=%s): %s", prefix, graph, phaseClass, before);
-                        if (NDCV.getValue() == INFO) {
-                            System.out.println(error.getMessage());
-                        } else if (NDCV.getValue() == VERBOSE) {
-                            error.printStackTrace(System.out);
-                        } else {
-                            assert NDCV.getValue() == FATAL;
-                            throw error;
-                        }
-                    }
+    public void verify(Object object, String message) {
+        if (NDCV.getValue() != OFF && object instanceof StructuredGraph) {
+            StructuredGraph graph = (StructuredGraph) object;
+            List<Node> before = graph.getNodes().snapshot();
+            new DeadCodeEliminationPhase().run(graph);
+            List<Node> after = graph.getNodes().snapshot();
+            assert after.size() <= before.size();
+            if (before.size() != after.size()) {
+                before.removeAll(after);
+                String prefix = message == null ? "" : message + ": ";
+                GraalInternalError error = new GraalInternalError("%sfound dead nodes in %s: %s", prefix, graph, before);
+                if (NDCV.getValue() == INFO) {
+                    System.out.println(error.getMessage());
+                } else if (NDCV.getValue() == VERBOSE) {
+                    error.printStackTrace(System.out);
+                } else {
+                    assert NDCV.getValue() == FATAL;
+                    throw error;
                 }
             }
         }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Jun 30 16:14:00 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Jun 30 17:28:53 2014 +0200
@@ -687,24 +687,23 @@
         List<ReturnNode> returnNodes = snippet.getNodes(ReturnNode.class).snapshot();
         if (returnNodes.isEmpty()) {
             this.returnNode = null;
-            this.memoryMap = null;
         } else if (returnNodes.size() == 1) {
             this.returnNode = returnNodes.get(0);
-            this.memoryMap = returnNode.getMemoryMap();
         } else {
             MergeNode merge = snippet.add(new MergeNode());
             List<MemoryMapNode> memMaps = returnNodes.stream().map(n -> n.getMemoryMap()).collect(Collectors.toList());
             ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes, null);
             this.returnNode = snippet.add(new ReturnNode(returnValue));
             MemoryMapImpl mmap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps);
-            this.memoryMap = snippet.unique(new MemoryMapNode(mmap.getMap()));
-            merge.setNext(this.returnNode);
-
+            MemoryMapNode memoryMap = snippet.unique(new MemoryMapNode(mmap.getMap()));
+            this.returnNode.setMemoryMap(memoryMap);
             for (MemoryMapNode mm : memMaps) {
-                if (mm.isAlive()) {
-                    mm.safeDelete();
+                if (mm != memoryMap && mm.isAlive()) {
+                    assert mm.usages().isEmpty();
+                    GraphUtil.killWithUnusedFloatingInputs(mm);
                 }
             }
+            merge.setNext(this.returnNode);
         }
 
         this.sideEffectNodes = curSideEffectNodes;
@@ -794,11 +793,6 @@
     private final ArrayList<Node> nodes;
 
     /**
-     * Map of killing locations to memory checkpoints (nodes).
-     */
-    private final MemoryMapNode memoryMap;
-
-    /**
      * Times instantiations of this template.
      *
      * @see SnippetInfo#instantiationTimer
@@ -957,6 +951,7 @@
             // no floating reads yet, ignore locations created while lowering
             return true;
         }
+        MemoryMapNode memoryMap = returnNode.getMemoryMap();
         if (memoryMap == null || memoryMap.isEmpty()) {
             // there are no kills in the snippet graph
             return true;
@@ -1018,6 +1013,7 @@
 
         @Override
         public MemoryNode getLastLocationAccess(LocationIdentity locationIdentity) {
+            MemoryMapNode memoryMap = returnNode.getMemoryMap();
             assert memoryMap != null : "no memory map stored for this snippet graph (snippet doesn't have a ReturnNode?)";
             MemoryNode lastLocationAccess = memoryMap.getLastLocationAccess(locationIdentity);
             assert lastLocationAccess != null;
@@ -1030,7 +1026,7 @@
 
         @Override
         public Collection<LocationIdentity> getLocations() {
-            return memoryMap.getLocations();
+            return returnNode.getMemoryMap().getLocations();
         }
     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Mon Jun 30 16:14:00 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Mon Jun 30 17:28:53 2014 +0200
@@ -91,7 +91,7 @@
                 }
 
                 // apply the effects collected during this iteration
-                HashSetNodeEventListener listener = new HashSetNodeEventListener.ExceptForAddedNodes();
+                HashSetNodeEventListener listener = new HashSetNodeEventListener();
                 try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
                     closure.applyEffects();
                 }