changeset 8401:701290361dad

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Wed, 20 Mar 2013 14:01:43 +0100
parents afb190b1eeb3 (diff) 0e2c530885d1 (current diff)
children c0db24536e97 0685ba2d4a4f
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java
diffstat 29 files changed, 227 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -52,8 +52,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -70,8 +70,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return locationIdentity;
+    public Object[] getLocationIdentities() {
+        return new Object[]{locationIdentity};
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -44,8 +44,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -116,14 +116,15 @@
             ResolvedJavaType type = getConcreteType(obj.objectStamp(), tool.getAssumptions());
             if (isCloneableType(type, tool.getMetaAccessProvider())) {
                 if (!type.isArray()) {
-                    ResolvedJavaField[] fields = type.getInstanceFields(true);
+                    VirtualInstanceNode newVirtual = new VirtualInstanceNode(type);
+                    ResolvedJavaField[] fields = newVirtual.getFields();
+
                     ValueNode[] state = new ValueNode[fields.length];
                     final LoadFieldNode[] loads = new LoadFieldNode[fields.length];
                     for (int i = 0; i < fields.length; i++) {
                         state[i] = loads[i] = graph().add(new LoadFieldNode(obj, fields[i]));
                     }
 
-                    VirtualObjectNode newVirtual = new VirtualInstanceNode(type, fields);
                     final StructuredGraph structuredGraph = (StructuredGraph) graph();
                     tool.customAction(new Runnable() {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -109,8 +109,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -162,8 +162,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     public FrameState stateDuring() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -30,7 +30,7 @@
 public class StartNode extends BeginStateSplitNode implements MemoryCheckpoint {
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.debug;
+
+import java.util.*;
+
+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.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * This node can be used to add a counter to the code that will estimate the dynamic number of calls
+ * by adding an increment to the compiled code. This should of course only be used for
+ * debugging/testing purposes, and is not 100% accurate (because of concurrency issues while
+ * accessing the counters).
+ * 
+ * A unique counter will be created for each unique String passed to the constructor.
+ */
+public class DynamicCounterNode extends FixedWithNextNode implements Lowerable {
+
+    private static final int MAX_COUNTERS = 10 * 1024;
+    private static final long[] COUNTERS = new long[MAX_COUNTERS];
+    private static final HashMap<String, Integer> INDEXES = new HashMap<>();
+    private final String name;
+    private final boolean addContext;
+
+    public DynamicCounterNode(String name, boolean addContext) {
+        super(StampFactory.forVoid());
+        this.name = name;
+        this.addContext = addContext;
+    }
+
+    private static synchronized int getIndex(String name) {
+        Integer index = INDEXES.get(name);
+        if (index == null) {
+            index = INDEXES.size();
+            if (index == 0) {
+                Runtime.getRuntime().addShutdownHook(new Thread() {
+
+                    @Override
+                    public void run() {
+                        dump();
+                    }
+                });
+            }
+            INDEXES.put(name, index);
+            if (index >= MAX_COUNTERS) {
+                throw new GraalInternalError("too many dynamic counters");
+            }
+            return index;
+        } else {
+            return index;
+        }
+    }
+
+    private static synchronized void dump() {
+        TreeMap<Long, String> sorted = new TreeMap<>();
+
+        long sum = 0;
+        for (int i = 0; i < MAX_COUNTERS; i++) {
+            sum += COUNTERS[i];
+        }
+        int cnt = 0;
+        for (Map.Entry<String, Integer> entry : INDEXES.entrySet()) {
+            sorted.put(COUNTERS[entry.getValue()] * MAX_COUNTERS + cnt++, entry.getKey());
+        }
+
+        for (Map.Entry<Long, String> entry : sorted.entrySet()) {
+            System.out.println((entry.getKey() / MAX_COUNTERS) + ": " + entry.getValue());
+        }
+        System.out.println(sum + ": total");
+
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        int index = addContext ? getIndex(name + " @ " + MetaUtil.format("%h.%n", ((StructuredGraph) graph()).method())) : getIndex(name);
+
+        StructuredGraph graph = (StructuredGraph) graph();
+        ConstantNode arrayConstant = ConstantNode.forObject(COUNTERS, tool.getRuntime(), graph);
+        ConstantNode indexConstant = ConstantNode.forInt(index, graph);
+        LoadIndexedNode load = graph.add(new LoadIndexedNode(arrayConstant, indexConstant, Kind.Long));
+        IntegerAddNode add = graph.add(new IntegerAddNode(Kind.Long, load, ConstantNode.forLong(1, graph)));
+        StoreIndexedNode store = graph.add(new StoreIndexedNode(arrayConstant, indexConstant, Kind.Long, add));
+
+        graph.addBeforeFixed(this, load);
+        graph.addBeforeFixed(this, store);
+        graph.removeFixed(this);
+    }
+
+    public static void createCounter(String name, FixedNode before, boolean addContext) {
+        StructuredGraph graph = (StructuredGraph) before.graph();
+        DynamicCounterNode counter = graph.add(new DynamicCounterNode(name, addContext));
+        graph.addBeforeFixed(before, counter);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Wed Mar 20 14:01:43 2013 +0100
@@ -29,7 +29,7 @@
 
     ValueNode object();
 
-    LocationNode location();
+    LocationNode nullCheckLocation();
 
     void setNullCheck(boolean check);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -30,7 +30,8 @@
 
 /**
  * Accesses a value at an memory address specified by an {@linkplain #object object} and a
- * {@linkplain #location() location}. The access does not include a null check on the object.
+ * {@linkplain #nullCheckLocation() location}. The access does not include a null check on the
+ * object.
  */
 public abstract class AccessNode extends FixedWithNextNode implements Access {
 
@@ -46,6 +47,10 @@
         return (LocationNode) location;
     }
 
+    public LocationNode nullCheckLocation() {
+        return (LocationNode) location;
+    }
+
     public boolean getNullCheck() {
         return nullCheck;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -43,6 +43,10 @@
         return location;
     }
 
+    public LocationNode nullCheckLocation() {
+        return location;
+    }
+
     public boolean getNullCheck() {
         return nullCheck;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -58,6 +58,6 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        return ReadNode.canonicalizeRead(this, tool);
+        return ReadNode.canonicalizeRead(this, location(), object(), tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -43,8 +43,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Wed Mar 20 14:01:43 2013 +0100
@@ -26,8 +26,8 @@
 
 /**
  * This interface marks is used for subclasses of {@link FixedNode} that kill a set of memory
- * locations represented by a location identity (i.e. change a value at one or more locations that
- * belong to this location identity).
+ * locations represented by location identities (i.e. change a value at one or more locations that
+ * belong to these location identities).
  */
 public interface MemoryCheckpoint {
 
@@ -35,8 +35,8 @@
      * This method is used to determine which set of memory locations is killed by this node.
      * Returning the special value {@link LocationNode#ANY_LOCATION} will kill all memory locations.
      * 
-     * @return the identity of the location killed by this node.
+     * @return the identities of all locations killed by this node.
      */
-    Object getLocationIdentity();
+    Object[] getLocationIdentities();
 
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -62,35 +62,35 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        return canonicalizeRead(this, tool);
+        return canonicalizeRead(this, location(), object(), tool);
     }
 
-    public static ValueNode canonicalizeRead(Access read, CanonicalizerTool tool) {
+    public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool) {
         MetaAccessProvider runtime = tool.runtime();
-        if (runtime != null && read.object() != null && read.object().isConstant()) {
-            if (read.location().locationIdentity() == LocationNode.FINAL_LOCATION && read.location().getClass() == LocationNode.class) {
-                long displacement = read.location().displacement();
-                Kind kind = read.location().getValueKind();
-                if (read.object().kind() == Kind.Object) {
-                    Object base = read.object().asConstant().asObject();
+        if (runtime != null && object != null && object.isConstant()) {
+            if (location.locationIdentity() == LocationNode.FINAL_LOCATION && location.getClass() == LocationNode.class) {
+                long displacement = location.displacement();
+                Kind kind = location.getValueKind();
+                if (object.kind() == Kind.Object) {
+                    Object base = object.asConstant().asObject();
                     if (base != null) {
                         Constant constant = tool.runtime().readUnsafeConstant(kind, base, displacement);
                         if (constant != null) {
-                            return ConstantNode.forConstant(constant, runtime, read.node().graph());
+                            return ConstantNode.forConstant(constant, runtime, read.graph());
                         }
                     }
-                } else if (read.object().kind() == Kind.Long || read.object().kind().getStackKind() == Kind.Int) {
-                    long base = read.object().asConstant().asLong();
+                } else if (object.kind() == Kind.Long || object.kind().getStackKind() == Kind.Int) {
+                    long base = object.asConstant().asLong();
                     if (base != 0L) {
                         Constant constant = tool.runtime().readUnsafeConstant(kind, null, base + displacement);
                         if (constant != null) {
-                            return ConstantNode.forConstant(constant, runtime, read.node().graph());
+                            return ConstantNode.forConstant(constant, runtime, read.graph());
                         }
                     }
                 }
             }
         }
-        return (ValueNode) read;
+        return read;
     }
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -49,8 +49,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -72,8 +72,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -37,8 +37,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -66,7 +66,7 @@
     public static native void writeMemory(Object object, Object value, Object location);
 
     @Override
-    public Object getLocationIdentity() {
-        return location().locationIdentity();
+    public Object[] getLocationIdentities() {
+        return new Object[]{location().locationIdentity()};
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -71,8 +71,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -42,8 +42,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -41,8 +41,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     public void lower(LoweringTool tool) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -42,8 +42,8 @@
     }
 
     @Override
-    public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
     }
 
     public void lower(LoweringTool tool) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -95,12 +95,12 @@
     public void virtualize(VirtualizerTool tool) {
         if (instanceClass != null) {
             assert !instanceClass().isArray();
-            ResolvedJavaField[] fields = instanceClass().getInstanceFields(true);
+            VirtualInstanceNode virtualObject = new VirtualInstanceNode(instanceClass());
+            ResolvedJavaField[] fields = virtualObject.getFields();
             ValueNode[] state = new ValueNode[fields.length];
             for (int i = 0; i < state.length; i++) {
                 state[i] = ConstantNode.defaultForKind(fields[i].getType().getKind(), graph());
             }
-            VirtualObjectNode virtualObject = new VirtualInstanceNode(instanceClass(), fields);
             tool.createVirtualObject(virtualObject, state, 0);
             tool.replaceWithVirtual(virtualObject);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -32,7 +32,7 @@
  * This node is used to perform the finalizer registration at the end of the java.lang.Object
  * constructor.
  */
-public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable {
+public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable, Virtualizable {
 
     public static final Descriptor REGISTER_FINALIZER = new Descriptor("registerFinalizer", true, void.class, Object.class);
 
@@ -74,4 +74,12 @@
 
         return this;
     }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        State state = tool.getObjectState(object);
+        if (state != null && !state.getVirtualObject().type().hasFinalizer()) {
+            tool.delete();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Wed Mar 20 14:01:43 2013 +0100
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.nodes.virtual;
 
-import java.util.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 
@@ -32,21 +30,10 @@
 
     private final ResolvedJavaType type;
     private final ResolvedJavaField[] fields;
-    private final HashMap<ResolvedJavaField, Integer> fieldMap;
 
-    public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
+    public VirtualInstanceNode(ResolvedJavaType type) {
         this.type = type;
-        this.fields = fields;
-        fieldMap = new HashMap<>();
-        for (int i = 0; i < fields.length; i++) {
-            fieldMap.put(fields[i], i);
-        }
-    }
-
-    private VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields, HashMap<ResolvedJavaField, Integer> fieldMap) {
-        this.type = type;
-        this.fields = fields;
-        this.fieldMap = fieldMap;
+        this.fields = type.getInstanceFields(true);
     }
 
     @Override
@@ -63,6 +50,10 @@
         return fields[index];
     }
 
+    public ResolvedJavaField[] getFields() {
+        return fields;
+    }
+
     @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Name) {
@@ -78,8 +69,13 @@
     }
 
     public int fieldIndex(ResolvedJavaField field) {
-        Integer index = fieldMap.get(field);
-        return index == null ? -1 : index;
+        // on average fields.length == ~6, so a linear search is fast enough
+        for (int i = 0; i < fields.length; i++) {
+            if (fields[i] == field) {
+                return i;
+            }
+        }
+        return -1;
     }
 
     @Override
@@ -95,6 +91,6 @@
 
     @Override
     public VirtualInstanceNode duplicate() {
-        return new VirtualInstanceNode(type, fields, fieldMap);
+        return new VirtualInstanceNode(type);
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Mar 20 14:01:43 2013 +0100
@@ -84,7 +84,9 @@
         @Override
         protected void processNode(FixedNode node, Set<Object> currentState) {
             if (node instanceof MemoryCheckpoint) {
-                currentState.add(((MemoryCheckpoint) node).getLocationIdentity());
+                for (Object identity : ((MemoryCheckpoint) node).getLocationIdentities()) {
+                    currentState.add(identity);
+                }
             }
         }
 
@@ -132,10 +134,12 @@
         }
 
         private void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) {
-            if (checkpoint.getLocationIdentity() == LocationNode.ANY_LOCATION) {
-                state.lastMemorySnapshot.clear();
+            for (Object identity : checkpoint.getLocationIdentities()) {
+                if (identity == LocationNode.ANY_LOCATION) {
+                    state.lastMemorySnapshot.clear();
+                }
+                state.lastMemorySnapshot.put(identity, (ValueNode) checkpoint);
             }
-            state.lastMemorySnapshot.put(checkpoint.getLocationIdentity(), (ValueNode) checkpoint);
         }
 
         private void processRead(ReadNode readNode, MemoryMap state) {
@@ -210,7 +214,9 @@
                  * needs to choose by putting in the location identity on both successors.
                  */
                 InvokeWithExceptionNode checkpoint = (InvokeWithExceptionNode) node.predecessor();
-                result.lastMemorySnapshot.put(checkpoint.getLocationIdentity(), node);
+                for (Object identity : checkpoint.getLocationIdentities()) {
+                    result.lastMemorySnapshot.put(identity, node);
+                }
             }
             return result;
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Mar 20 14:01:43 2013 +0100
@@ -133,11 +133,11 @@
             } else if (node instanceof Access) {
                 Access access = (Access) node;
                 GuardNode guard = nullGuarded.get(access.object());
-                if (guard != null && isImplicitNullCheck(access.location(), target)) {
+                if (guard != null && isImplicitNullCheck(access.nullCheckLocation(), target)) {
                     NodeInputList<ValueNode> dependencies = ((ValueNode) access).dependencies();
                     dependencies.remove(guard);
                     if (access instanceof FloatingReadNode) {
-                        ReadNode read = graph.add(new ReadNode(access.object(), access.location(), ((FloatingReadNode) access).stamp(), dependencies));
+                        ReadNode read = graph.add(new ReadNode(access.object(), access.nullCheckLocation(), ((FloatingReadNode) access).stamp(), dependencies));
                         node.replaceAndDelete(read);
                         access = read;
                         lastFixed.setNext(read);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Mar 20 12:00:18 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Mar 20 14:01:43 2013 +0100
@@ -64,12 +64,13 @@
                 if (node instanceof FloatingReadNode) {
                     currentState.add((FloatingReadNode) node);
                 } else if (node instanceof MemoryCheckpoint) {
-                    Object identity = ((MemoryCheckpoint) node).getLocationIdentity();
-                    for (Iterator<FloatingReadNode> iter = currentState.iterator(); iter.hasNext();) {
-                        FloatingReadNode read = iter.next();
-                        FixedNode fixed = (FixedNode) node;
-                        if (identity == LocationNode.ANY_LOCATION || read.location().locationIdentity() == identity) {
-                            addPhantomReference(read, fixed);
+                    for (Object identity : ((MemoryCheckpoint) node).getLocationIdentities()) {
+                        for (Iterator<FloatingReadNode> iter = currentState.iterator(); iter.hasNext();) {
+                            FloatingReadNode read = iter.next();
+                            FixedNode fixed = (FixedNode) node;
+                            if (identity == LocationNode.ANY_LOCATION || read.location().locationIdentity() == identity) {
+                                addPhantomReference(read, fixed);
+                            }
                         }
                     }
                 }