changeset 9810:b49fdcee6cb0

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 23 May 2013 14:44:01 +0200
parents a8a5d5832def (current diff) 8e33b4ebfef1 (diff)
children 097630441baf
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallStateSplitNode.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyValueUsage.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java
diffstat 140 files changed, 1886 insertions(+), 1235 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Thu May 23 14:44:01 2013 +0200
@@ -161,8 +161,25 @@
     /**
      * Determine the maximum vector length supported for vector operations on values of a given
      * {@link Kind}.
+     * 
+     * @param kind the kind of the individual vector elements
+     * @return the maximum supported vector size
      */
-    public int getMaxVectorLength(@SuppressWarnings("unused") Kind kind) {
+    public int getMaxVectorLength(Kind kind) {
+        return 1;
+    }
+
+    /**
+     * Get a natively supported vector length for breaking down some vector operation on a constant
+     * length vector.
+     * 
+     * @param kind the kind of the individual vector elements
+     * @param maxLength the maximum length that should be returned
+     * @param arithmetic whether the vector length needs to support arithmetic operations or just
+     *            load and store
+     * @return a supported vector size, but at most {@code maxLength}
+     */
+    public int getSupportedVectorLength(Kind kind, int maxLength, boolean arithmetic) {
         return 1;
     }
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java	Thu May 23 14:44:01 2013 +0200
@@ -213,7 +213,8 @@
     public boolean equals(Object obj) {
         if (obj instanceof Register) {
             Register other = (Register) obj;
-            if (number == other.number && name.equals(other.name)) {
+            if (number == other.number) {
+                assert name.equals(other.name);
                 assert encoding == other.encoding;
                 assert registerCategory == other.registerCategory;
                 return true;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Thu May 23 14:44:01 2013 +0200
@@ -120,7 +120,7 @@
     }
 
     public static boolean sameRegister(Value v1, Value v2) {
-        return isRegister(v1) && isRegister(v2) && asRegister(v1) == asRegister(v2);
+        return isRegister(v1) && isRegister(v2) && asRegister(v1).equals(asRegister(v2));
     }
 
     public static boolean sameRegister(Value v1, Value v2, Value v3) {
@@ -128,7 +128,7 @@
     }
 
     public static boolean differentRegisters(Value v1, Value v2) {
-        return !isRegister(v1) || !isRegister(v2) || asRegister(v1) != asRegister(v2);
+        return !isRegister(v1) || !isRegister(v2) || !asRegister(v1).equals(asRegister(v2));
     }
 
     public static boolean differentRegisters(Value v1, Value v2, Value v3) {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Thu May 23 14:44:01 2013 +0200
@@ -147,7 +147,8 @@
             } else {
                 Kind componentKind = type.getComponentType().getKind().getStackKind();
                 for (int i = 0; i < values.length; i++) {
-                    assert values[i].getKind().getStackKind() == componentKind : values[i].getKind() + " != " + componentKind;
+                    assert values[i].getKind().getStackKind() == componentKind || componentKind.getBitCount() >= values[i].getKind().getStackKind().getBitCount() : values[i].getKind() + " != " +
+                                    componentKind;
                 }
             }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java	Thu May 23 14:44:01 2013 +0200
@@ -0,0 +1,151 @@
+/*
+ * 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.api.meta;
+
+import java.io.*;
+
+/**
+ * This profile object represents a certain set of profiling information at a specific BCI. The
+ * precision of the supplied values may vary, but a runtime that provides this information should be
+ * aware that it will be used to guide performance-critical decisions like speculative inlining,
+ * etc.
+ */
+public abstract class AbstractJavaProfile<T extends AbstractProfiledItem<U>, U> implements Serializable {
+
+    private static final long serialVersionUID = 5493379044459116749L;
+
+    private final double notRecordedProbability;
+    private final T[] pitems;
+
+    public AbstractJavaProfile(double notRecordedProbability, T[] pitems) {
+        this.pitems = pitems;
+        assert notRecordedProbability != Double.NaN;
+        this.notRecordedProbability = notRecordedProbability;
+        assert isSorted();
+    }
+
+    /**
+     * Determines if an array of profiled items are sorted in descending order of their
+     * probabilities.
+     */
+    private boolean isSorted() {
+        for (int i = 1; i < pitems.length; i++) {
+            if (pitems[i - 1].getProbability() < pitems[i].getProbability()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Returns the estimated probability of all types that could not be recorded due to profiling
+     * limitations.
+     * 
+     * @return double value >= 0.0 and <= 1.0
+     */
+    public double getNotRecordedProbability() {
+        return notRecordedProbability;
+    }
+
+    protected T[] getItems() {
+        return pitems;
+    }
+
+    /**
+     * Searches for an entry of a given resolved Java type.
+     * 
+     * @param type the type for which an entry should be searched
+     * @return the entry or null if no entry for this type can be found
+     */
+    public T findEntry(ResolvedJavaType type) {
+        if (pitems != null) {
+            for (T pt : pitems) {
+                if (pt.getItem() == type) {
+                    return pt;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(this.getClass().getName());
+        builder.append("[");
+        if (pitems != null) {
+            for (T pt : pitems) {
+                builder.append(pt.toString());
+                builder.append(", ");
+            }
+        }
+        builder.append(this.notRecordedProbability);
+        builder.append("]");
+        return builder.toString();
+    }
+
+    public boolean isIncluded(U item) {
+        if (this.getNotRecordedProbability() > 0.0) {
+            return true;
+        } else {
+            for (int i = 0; i < getItems().length; i++) {
+                T pitem = getItems()[i];
+                U curType = pitem.getItem();
+                if (curType == item) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if (getClass() == other.getClass()) {
+            AbstractJavaProfile javaTypeProfile = (AbstractJavaProfile) other;
+            if (javaTypeProfile.notRecordedProbability != notRecordedProbability) {
+                return false;
+            }
+            if (javaTypeProfile.pitems.length != pitems.length) {
+                return false;
+            }
+
+            for (int i = 0; i < pitems.length; ++i) {
+                if (!pitems[i].equals(javaTypeProfile.pitems[i])) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return (int) Double.doubleToLongBits(notRecordedProbability) + pitems.length * 13;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractProfiledItem.java	Thu May 23 14:44:01 2013 +0200
@@ -0,0 +1,99 @@
+/*
+ * 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.api.meta;
+
+import java.io.*;
+
+/**
+ * A profiled type that has a probability. Profiled types are naturally sorted in descending order
+ * of their probabilities.
+ */
+public abstract class AbstractProfiledItem<T> implements Comparable<AbstractProfiledItem>, Serializable {
+
+    private static final long serialVersionUID = 7838575753661305744L;
+
+    protected final T item;
+    protected final double probability;
+
+    public AbstractProfiledItem(T item, double probability) {
+        assert item != null;
+        assert probability >= 0.0D && probability <= 1.0D;
+        this.item = item;
+        this.probability = probability;
+    }
+
+    protected T getItem() {
+        return item;
+    }
+
+    /**
+     * Returns the estimated probability of {@link #getItem()}.
+     * 
+     * @return double value >= 0.0 and <= 1.0
+     */
+    public double getProbability() {
+        return probability;
+    }
+
+    @Override
+    public int compareTo(AbstractProfiledItem o) {
+        if (getProbability() > o.getProbability()) {
+            return -1;
+        } else if (getProbability() < o.getProbability()) {
+            return 1;
+        }
+        return 0;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        long temp;
+        temp = Double.doubleToLongBits(probability);
+        result = prime * result + (int) (temp ^ (temp >>> 32));
+        result = prime * result + item.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        AbstractProfiledItem other = (AbstractProfiledItem) obj;
+        if (Double.doubleToLongBits(probability) != Double.doubleToLongBits(other.probability)) {
+            return false;
+        }
+        return item.equals(other.item);
+    }
+
+    @Override
+    public abstract String toString();
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java	Thu May 23 14:44:01 2013 +0200
@@ -48,6 +48,11 @@
     }
 
     @Override
+    public JavaMethodProfile getMethodProfile(int bci) {
+        return null;
+    }
+
+    @Override
     public double getBranchTakenProbability(int bci) {
         return -1;
     }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ForeignCallDescriptor.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ForeignCallDescriptor.java	Thu May 23 14:44:01 2013 +0200
@@ -33,6 +33,9 @@
  * <li>The callee has different register saving semantics. For example, the callee may save all
  * registers (apart from some specified temporaries) in which case the register allocator doesn't
  * not need to spill all live registers around the call site.</li>
+ * <li>The call does not occur at an INVOKE* bytecode. Such a call could be transformed into a
+ * standard Java call if the foreign routine is a normal Java method and the runtime supports
+ * linking Java calls at arbitrary bytecodes.</li>
  * </ul>
  */
 public class ForeignCallDescriptor {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaMethodProfile.java	Thu May 23 14:44:01 2013 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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.api.meta;
+
+import com.oracle.graal.api.meta.JavaMethodProfile.ProfiledMethod;
+
+/**
+ * This profile object represents the method profile at a specific BCI. The precision of the
+ * supplied values may vary, but a runtime that provides this information should be aware that it
+ * will be used to guide performance-critical decisions like speculative inlining, etc.
+ */
+public final class JavaMethodProfile extends AbstractJavaProfile<ProfiledMethod, ResolvedJavaMethod> {
+
+    private static final long serialVersionUID = -1440572119913692689L;
+
+    public JavaMethodProfile(double notRecordedProbability, ProfiledMethod[] pitems) {
+        super(notRecordedProbability, pitems);
+    }
+
+    public ProfiledMethod[] getMethods() {
+        return super.getItems();
+    }
+
+    public static class ProfiledMethod extends AbstractProfiledItem<ResolvedJavaMethod> {
+
+        private static final long serialVersionUID = 5418813647187024693L;
+
+        public ProfiledMethod(ResolvedJavaMethod item, double probability) {
+            super(item, probability);
+        }
+
+        /**
+         * Returns the type for this profile entry.
+         */
+        public ResolvedJavaMethod getMethod() {
+            return getItem();
+        }
+
+        @Override
+        public String toString() {
+            return "{" + item.getName() + ", " + probability + "}";
+        }
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Thu May 23 14:44:01 2013 +0200
@@ -22,134 +22,26 @@
  */
 package com.oracle.graal.api.meta;
 
-import java.io.*;
 import java.util.*;
 
-import com.oracle.graal.api.meta.ProfilingInfo.*;
+import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
+import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 
 /**
  * This profile object represents the type profile at a specific BCI. The precision of the supplied
  * values may vary, but a runtime that provides this information should be aware that it will be
  * used to guide performance-critical decisions like speculative inlining, etc.
  */
-public final class JavaTypeProfile implements Serializable {
+public final class JavaTypeProfile extends AbstractJavaProfile<ProfiledType, ResolvedJavaType> {
 
     private static final long serialVersionUID = -6877016333706838441L;
-
-    /**
-     * A profiled type that has a probability. Profiled types are naturally sorted in descending
-     * order of their probabilities.
-     */
-    public static final class ProfiledType implements Comparable<ProfiledType>, Serializable {
-
-        private static final long serialVersionUID = 7838575753661305744L;
-
-        public static final ProfiledType[] EMPTY_ARRAY = new ProfiledType[0];
-
-        private final ResolvedJavaType type;
-        private final double probability;
-
-        public ProfiledType(ResolvedJavaType type, double probability) {
-            assert type != null;
-            assert probability >= 0.0D && probability <= 1.0D;
-            this.type = type;
-            this.probability = probability;
-        }
-
-        /**
-         * Returns the type for this profile entry.
-         */
-        public ResolvedJavaType getType() {
-            return type;
-        }
-
-        /**
-         * Returns the estimated probability of {@link #getType()}.
-         * 
-         * @return double value >= 0.0 and <= 1.0
-         */
-        public double getProbability() {
-            return probability;
-        }
-
-        @Override
-        public int compareTo(ProfiledType o) {
-            if (getProbability() > o.getProbability()) {
-                return -1;
-            } else if (getProbability() < o.getProbability()) {
-                return 1;
-            }
-            return 0;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            long temp;
-            temp = Double.doubleToLongBits(probability);
-            result = prime * result + (int) (temp ^ (temp >>> 32));
-            result = prime * result + type.hashCode();
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            ProfiledType other = (ProfiledType) obj;
-            if (Double.doubleToLongBits(probability) != Double.doubleToLongBits(other.probability)) {
-                return false;
-            }
-            return type.equals(other.type);
-        }
-
-        @Override
-        public String toString() {
-            return "{" + type.getName() + ", " + probability + "}";
-        }
-    }
+    private static final ProfiledType[] EMPTY_ARRAY = new ProfiledType[0];
 
     private final TriState nullSeen;
-    private final double notRecordedProbability;
-    private final ProfiledType[] ptypes;
 
-    /**
-     * Determines if an array of profiled types are sorted in descending order of their
-     * probabilities.
-     */
-    private static boolean isSorted(ProfiledType[] ptypes) {
-        for (int i = 1; i < ptypes.length; i++) {
-            if (ptypes[i - 1].getProbability() < ptypes[i].getProbability()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public JavaTypeProfile(TriState nullSeen, double notRecordedProbability, ProfiledType... ptypes) {
+    public JavaTypeProfile(TriState nullSeen, double notRecordedProbability, ProfiledType[] pitems) {
+        super(notRecordedProbability, pitems);
         this.nullSeen = nullSeen;
-        this.ptypes = ptypes;
-        assert notRecordedProbability != Double.NaN;
-        this.notRecordedProbability = notRecordedProbability;
-        assert isSorted(ptypes);
-    }
-
-    /**
-     * Returns the estimated probability of all types that could not be recorded due to profiling
-     * limitations.
-     * 
-     * @return double value >= 0.0 and <= 1.0
-     */
-    public double getNotRecordedProbability() {
-        return notRecordedProbability;
     }
 
     /**
@@ -165,41 +57,7 @@
      * type and a negative type is not.
      */
     public ProfiledType[] getTypes() {
-        return ptypes;
-    }
-
-    /**
-     * Searches for an entry of a given resolved Java type.
-     * 
-     * @param type the type for which an entry should be searched
-     * @return the entry or null if no entry for this type can be found
-     */
-    public ProfiledType findEntry(ResolvedJavaType type) {
-        if (ptypes != null) {
-            for (ProfiledType pt : ptypes) {
-                if (pt.getType() == type) {
-                    return pt;
-                }
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append("JavaTypeProfile[");
-        builder.append(this.nullSeen);
-        builder.append(", ");
-        if (ptypes != null) {
-            for (ProfiledType pt : ptypes) {
-                builder.append(pt.toString());
-                builder.append(", ");
-            }
-        }
-        builder.append(this.notRecordedProbability);
-        builder.append("]");
-        return builder.toString();
+        return getItems();
     }
 
     public JavaTypeProfile restrict(JavaTypeProfile otherProfile) {
@@ -214,57 +72,42 @@
         }
 
         ArrayList<ProfiledType> result = new ArrayList<>();
-        for (int i = 0; i < getTypes().length; i++) {
-            ProfiledType ptype = getTypes()[i];
-            ResolvedJavaType type = ptype.getType();
+        for (int i = 0; i < getItems().length; i++) {
+            ProfiledType ptype = getItems()[i];
+            ResolvedJavaType type = ptype.getItem();
             if (otherProfile.isIncluded(type)) {
                 result.add(ptype);
             }
         }
 
-        TriState newNullSeen = (otherProfile.getNullSeen() == TriState.FALSE) ? TriState.FALSE : this.nullSeen;
-        double newNotRecorded = this.notRecordedProbability;
+        TriState newNullSeen = (otherProfile.getNullSeen() == TriState.FALSE) ? TriState.FALSE : getNullSeen();
+        double newNotRecorded = getNotRecordedProbability();
         return createAdjustedProfile(result, newNullSeen, newNotRecorded);
     }
 
-    public boolean isIncluded(ResolvedJavaType type) {
-        if (this.getNotRecordedProbability() > 0.0) {
-            return true;
-        } else {
-            for (int i = 0; i < getTypes().length; i++) {
-                ProfiledType ptype = getTypes()[i];
-                ResolvedJavaType curType = ptype.getType();
-                if (curType == type) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
     public JavaTypeProfile restrict(ResolvedJavaType declaredType, boolean nonNull) {
         ArrayList<ProfiledType> result = new ArrayList<>();
-        for (int i = 0; i < getTypes().length; i++) {
-            ProfiledType ptype = getTypes()[i];
-            ResolvedJavaType type = ptype.getType();
+        for (int i = 0; i < getItems().length; i++) {
+            ProfiledType ptype = getItems()[i];
+            ResolvedJavaType type = ptype.getItem();
             if (declaredType.isAssignableFrom(type)) {
                 result.add(ptype);
             }
         }
 
-        TriState newNullSeen = (nonNull) ? TriState.FALSE : this.nullSeen;
+        TriState newNullSeen = (nonNull) ? TriState.FALSE : getNullSeen();
         double newNotRecorded = this.getNotRecordedProbability();
         // Assume for the types not recorded, the incompatibility rate is the same.
-        if (getTypes().length != 0) {
-            newNotRecorded *= ((double) result.size() / (double) getTypes().length);
+        if (getItems().length != 0) {
+            newNotRecorded *= ((double) result.size() / (double) getItems().length);
         }
         return createAdjustedProfile(result, newNullSeen, newNotRecorded);
     }
 
     private JavaTypeProfile createAdjustedProfile(ArrayList<ProfiledType> result, TriState newNullSeen, double newNotRecorded) {
-        if (result.size() != this.getTypes().length || newNotRecorded != getNotRecordedProbability() || newNullSeen != this.nullSeen) {
+        if (result.size() != this.getItems().length || newNotRecorded != getNotRecordedProbability() || newNullSeen != getNullSeen()) {
             if (result.size() == 0) {
-                return new JavaTypeProfile(newNullSeen, 1.0, ProfiledType.EMPTY_ARRAY);
+                return new JavaTypeProfile(newNullSeen, 1.0, EMPTY_ARRAY);
             }
             double probabilitySum = 0.0;
             for (int i = 0; i < result.size(); i++) {
@@ -277,7 +120,7 @@
             ProfiledType[] newResult = new ProfiledType[result.size()];
             for (int i = 0; i < newResult.length; ++i) {
                 ProfiledType curType = result.get(i);
-                newResult[i] = new ProfiledType(curType.getType(), Math.min(1.0, curType.getProbability() * factor));
+                newResult[i] = new ProfiledType(curType.getItem(), Math.min(1.0, curType.getProbability() * factor));
             }
             double newNotRecordedTypeProbability = Math.min(1.0, newNotRecorded * factor);
             return new JavaTypeProfile(newNullSeen, newNotRecordedTypeProbability, newResult);
@@ -287,34 +130,32 @@
 
     @Override
     public boolean equals(Object other) {
-        if (other == this) {
-            return true;
-        }
-        if (other instanceof JavaTypeProfile) {
-            JavaTypeProfile javaTypeProfile = (JavaTypeProfile) other;
-            if (javaTypeProfile.nullSeen != nullSeen) {
-                return false;
-            }
-            if (javaTypeProfile.notRecordedProbability != notRecordedProbability) {
-                return false;
-            }
-            if (javaTypeProfile.ptypes.length != ptypes.length) {
-                return false;
-            }
-
-            for (int i = 0; i < ptypes.length; ++i) {
-                if (!ptypes[i].equals(javaTypeProfile.ptypes[i])) {
-                    return false;
-                }
-            }
-
-            return true;
-        }
-        return false;
+        return super.equals(other) && nullSeen.equals(((JavaTypeProfile) other).nullSeen);
     }
 
     @Override
     public int hashCode() {
-        return nullSeen.hashCode() + (int) Double.doubleToLongBits(notRecordedProbability) + ptypes.length * 13;
+        return nullSeen.hashCode() + super.hashCode();
+    }
+
+    public static class ProfiledType extends AbstractProfiledItem<ResolvedJavaType> {
+
+        private static final long serialVersionUID = 1481773321889860837L;
+
+        public ProfiledType(ResolvedJavaType item, double probability) {
+            super(item, probability);
+        }
+
+        /**
+         * Returns the type for this profile entry.
+         */
+        public ResolvedJavaType getType() {
+            return getItem();
+        }
+
+        @Override
+        public String toString() {
+            return "{" + item.getName() + ", " + probability + "}";
+        }
     }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Thu May 23 14:44:01 2013 +0200
@@ -362,8 +362,12 @@
             case Char:
             case Short:
                 return 16;
+            case Float:
+                return 32;
             case Int:
                 return 32;
+            case Double:
+                return 64;
             case Long:
                 return 64;
             default:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LocationIdentity.java	Thu May 23 14:44:01 2013 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.meta;
+
+/**
+ * Marker interface for location identities. Apart from the special values {@link #ANY_LOCATION} and
+ * {@link #FINAL_LOCATION}, a different location identity of two memory accesses guarantees that the
+ * two accesses do not interfere.
+ */
+public interface LocationIdentity {
+
+    /**
+     * Denotes any location. A write to such a location kills all values in a memory map during an
+     * analysis of memory accesses. A read from this location cannot be moved or coalesced with
+     * other reads because its interaction with other reads is not known.
+     */
+    LocationIdentity ANY_LOCATION = new NamedLocationIdentity("ANY_LOCATION");
+
+    /**
+     * Denotes the location of a value that is guaranteed to be final.
+     */
+    LocationIdentity FINAL_LOCATION = new NamedLocationIdentity("FINAL_LOCATION");
+
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Thu May 23 14:44:01 2013 +0200
@@ -96,8 +96,15 @@
     Constant readUnsafeConstant(Kind kind, Object base, long displacement);
 
     /**
-     * Determines if a given foreign call has a side-effect. Deoptimization cannot return execution
-     * to a point before a foreign call that has a side effect.
+     * Determines if a given foreign call is side-effect free. Deoptimization cannot return
+     * execution to a point before a foreign call that has a side effect.
      */
-    boolean hasSideEffect(ForeignCallDescriptor descriptor);
+    boolean isReexecutable(ForeignCallDescriptor descriptor);
+
+    /**
+     * Gets the set of memory locations killed by a given foreign call. Returning the special value
+     * {@link LocationIdentity#ANY_LOCATION} denotes that the call kills all memory locations.
+     * Returning any empty array denotes that the call does not kill any memory locations.
+     */
+    LocationIdentity[] getKilledLocationIdentities(ForeignCallDescriptor descriptor);
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Thu May 23 14:44:01 2013 +0200
@@ -28,7 +28,6 @@
 import java.lang.reflect.*;
 import java.util.*;
 
-import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 
 /**
@@ -546,21 +545,10 @@
             }
 
             JavaTypeProfile typeProfile = info.getTypeProfile(i);
-            if (typeProfile != null) {
-                ProfiledType[] ptypes = typeProfile.getTypes();
-                if (ptypes != null) {
-                    buf.append(String.format("types@%d:", i));
-                    for (int j = 0; j < ptypes.length; j++) {
-                        ProfiledType ptype = ptypes[j];
-                        buf.append(String.format(" %.6f (%s)%s", ptype.getProbability(), ptype.getType(), sep));
-                    }
-                    if (typeProfile.getNotRecordedProbability() != 0) {
-                        buf.append(String.format(" %.6f <other types>%s", typeProfile.getNotRecordedProbability(), sep));
-                    } else {
-                        buf.append(String.format(" <no other types>%s", sep));
-                    }
-                }
-            }
+            appendProfile(buf, typeProfile, i, "types", sep);
+
+            JavaMethodProfile methodProfile = info.getMethodProfile(i);
+            appendProfile(buf, methodProfile, i, "methods", sep);
         }
 
         boolean firstDeoptReason = true;
@@ -582,6 +570,24 @@
         return s.substring(0, s.length() - sep.length());
     }
 
+    private static void appendProfile(StringBuilder buf, AbstractJavaProfile profile, int bci, String type, String sep) {
+        if (profile != null) {
+            AbstractProfiledItem[] pitems = profile.getItems();
+            if (pitems != null) {
+                buf.append(String.format("%s@%d:", type, bci));
+                for (int j = 0; j < pitems.length; j++) {
+                    AbstractProfiledItem pitem = pitems[j];
+                    buf.append(String.format(" %.6f (%s)%s", pitem.getProbability(), pitem.getItem(), sep));
+                }
+                if (profile.getNotRecordedProbability() != 0) {
+                    buf.append(String.format(" %.6f <other %s>%s", profile.getNotRecordedProbability(), type, sep));
+                } else {
+                    buf.append(String.format(" <no other %s>%s", type, sep));
+                }
+            }
+        }
+    }
+
     /**
      * Converts a Java source-language class name into the internal form.
      * 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/NamedLocationIdentity.java	Thu May 23 14:44:01 2013 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.meta;
+
+import java.util.*;
+
+/**
+ * A {@link LocationIdentity} with a name.
+ */
+public class NamedLocationIdentity implements LocationIdentity {
+
+    protected final String name;
+
+    /**
+     * Creates a named unique location identity for read and write operations.
+     * 
+     * @param name the name of the new location identity
+     */
+    public NamedLocationIdentity(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    /**
+     * Returns the named location identity for an array of the given element kind. Array accesses of
+     * the same kind must have the same location identity unless an alias analysis guarantees that
+     * two distinct arrays are accessed.
+     */
+    public static LocationIdentity getArrayLocation(Kind elementKind) {
+        return ARRAY_LOCATIONS.get(elementKind);
+    }
+
+    private static final EnumMap<Kind, LocationIdentity> ARRAY_LOCATIONS = initArrayLocations();
+
+    private static EnumMap<Kind, LocationIdentity> initArrayLocations() {
+        EnumMap<Kind, LocationIdentity> result = new EnumMap<>(Kind.class);
+        for (Kind kind : Kind.values()) {
+            result.put(kind, new NamedLocationIdentity("Array: " + kind.getJavaName()));
+        }
+        return result;
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Thu May 23 14:44:01 2013 +0200
@@ -66,25 +66,31 @@
     /**
      * Returns the TypeProfile for the given BCI.
      * 
-     * @return Returns an JavaTypeProfile object, or null if not available.
+     * @return Returns a JavaTypeProfile object, or null if not available.
      */
     JavaTypeProfile getTypeProfile(int bci);
 
     /**
+     * Returns the MethodProfile for the given BCI.
+     * 
+     * @return Returns a JavaMethodProfile object, or null if not available.
+     */
+    JavaMethodProfile getMethodProfile(int bci);
+
+    /**
      * Returns information if the given BCI did ever throw an exception.
      * 
      * @return {@link TriState#TRUE} if the instruction has thrown an exception at least once,
-     *         {@link TriState#FALSE} if it never threw an exception, and
-     *         {@link TriState#UNKNOWN} if this information was not recorded.
+     *         {@link TriState#FALSE} if it never threw an exception, and {@link TriState#UNKNOWN}
+     *         if this information was not recorded.
      */
     TriState getExceptionSeen(int bci);
 
     /**
      * Returns information if null was ever seen for the given BCI.
      * 
-     * @return {@link TriState#TRUE} if null was seen for the instruction,
-     *         {@link TriState#FALSE} if null was NOT seen, and
-     *         {@link TriState#UNKNOWN} if this information was not recorded.
+     * @return {@link TriState#TRUE} if null was seen for the instruction, {@link TriState#FALSE} if
+     *         null was NOT seen, and {@link TriState#UNKNOWN} if this information was not recorded.
      */
     TriState getNullSeen(int bci);
 
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java	Thu May 23 14:44:01 2013 +0200
@@ -114,11 +114,11 @@
         StringBuilder s = new StringBuilder();
         s.append("[");
         String sep = "";
-        if (getBase() != Register.None) {
+        if (!getBase().equals(Register.None)) {
             s.append(getBase());
             sep = " + ";
         }
-        if (getIndex() != Register.None) {
+        if (!getIndex().equals(Register.None)) {
             s.append(sep).append(getIndex()).append(" * ").append(getScale().value);
             sep = " + ";
         }
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Thu May 23 14:44:01 2013 +0200
@@ -216,7 +216,7 @@
     }
 
     protected void emitOperandHelper(Register reg, AMD64Address addr) {
-        assert reg != Register.None;
+        assert !reg.equals(Register.None);
         emitOperandHelper(encode(reg), addr);
     }
 
@@ -230,14 +230,14 @@
         AMD64Address.Scale scale = addr.getScale();
         int disp = addr.getDisplacement();
 
-        if (base == Register.Frame) {
+        if (base.equals(Register.Frame)) {
             assert frameRegister != null : "cannot use register " + Register.Frame + " in assembler with null register configuration";
             base = frameRegister;
         }
 
-        if (base == AMD64.rip) { // also matches Placeholder
+        if (base.equals(AMD64.rip)) { // also matches Placeholder
             // [00 000 101] disp32
-            assert index == Register.None : "cannot use RIP relative addressing with index register";
+            assert index.equals(Register.None) : "cannot use RIP relative addressing with index register";
             emitByte(0x05 | regenc);
             emitInt(disp);
         } else if (base.isValid()) {
@@ -245,28 +245,28 @@
             if (index.isValid()) {
                 int indexenc = encode(index) << 3;
                 // [base + indexscale + disp]
-                if (disp == 0 && base != rbp && (base != r13)) {
+                if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
                     // [base + indexscale]
                     // [00 reg 100][ss index base]
-                    assert index != rsp : "illegal addressing mode";
+                    assert !index.equals(rsp) : "illegal addressing mode";
                     emitByte(0x04 | regenc);
                     emitByte(scale.log2 << 6 | indexenc | baseenc);
                 } else if (isByte(disp)) {
                     // [base + indexscale + imm8]
                     // [01 reg 100][ss index base] imm8
-                    assert index != rsp : "illegal addressing mode";
+                    assert !index.equals(rsp) : "illegal addressing mode";
                     emitByte(0x44 | regenc);
                     emitByte(scale.log2 << 6 | indexenc | baseenc);
                     emitByte(disp & 0xFF);
                 } else {
                     // [base + indexscale + disp32]
                     // [10 reg 100][ss index base] disp32
-                    assert index != rsp : "illegal addressing mode";
+                    assert !index.equals(rsp) : "illegal addressing mode";
                     emitByte(0x84 | regenc);
                     emitByte(scale.log2 << 6 | indexenc | baseenc);
                     emitInt(disp);
                 }
-            } else if (base == rsp || (base == r12)) {
+            } else if (base.equals(rsp) || base.equals(r12)) {
                 // [rsp + disp]
                 if (disp == 0) {
                     // [rsp]
@@ -288,8 +288,8 @@
                 }
             } else {
                 // [base + disp]
-                assert base != rsp && (base != r12) : "illegal addressing mode";
-                if (disp == 0 && base != rbp && (base != r13)) {
+                assert !base.equals(rsp) && !base.equals(r12) : "illegal addressing mode";
+                if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
                     // [base]
                     // [00 reg base]
                     emitByte(0x00 | regenc | baseenc);
@@ -310,7 +310,7 @@
                 int indexenc = encode(index) << 3;
                 // [indexscale + disp]
                 // [00 reg 100][ss index 101] disp32
-                assert index != rsp : "illegal addressing mode";
+                assert !index.equals(rsp) : "illegal addressing mode";
                 emitByte(0x04 | regenc);
                 emitByte(scale.log2 << 6 | indexenc | 0x05);
                 emitInt(disp);
@@ -531,7 +531,7 @@
             // cmpxchg r,[m] is equivalent to X86.rax, = CAS (m, X86.rax, r)
             cmpl(rax, adr);
             movl(rax, adr);
-            if (reg != rax) {
+            if (reg.equals(rax)) {
                 Label l = new Label();
                 jccb(ConditionFlag.NotEqual, l);
                 movl(adr, reg);
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java	Thu May 23 14:44:01 2013 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 
 /**
  * This class implements commonly used X86 code patterns.
@@ -255,7 +256,7 @@
     private AMD64Address trigPrologue(Register value) {
         assert value.getRegisterCategory() == AMD64.XMM;
         AMD64Address tmp = new AMD64Address(AMD64.rsp);
-        subq(AMD64.rsp, 8);
+        subq(AMD64.rsp, target.arch.getSizeInBytes(Kind.Double));
         movsd(tmp, value);
         fld_d(tmp);
         return tmp;
@@ -265,7 +266,7 @@
         assert dest.getRegisterCategory() == AMD64.XMM;
         fstp_d(tmp);
         movsd(dest, tmp);
-        addq(AMD64.rsp, 8);
+        addq(AMD64.rsp, target.arch.getSizeInBytes(Kind.Double));
     }
 
     /**
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu May 23 14:44:01 2013 +0200
@@ -135,7 +135,7 @@
 
     @Override
     public Variable emitMove(Value input) {
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getPlatformKind());
         emitMove(result, input);
         return result;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu May 23 14:44:01 2013 +0200
@@ -426,18 +426,29 @@
                 }
                 long start = System.currentTimeMillis();
                 PhasePlan phasePlan = new PhasePlan();
-                StructuredGraph graphCopy = graph.copy();
+                final StructuredGraph graphCopy = graph.copy();
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
                 phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                 phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
                 editPhasePlan(method, graph, phasePlan);
                 CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
-                CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
+                final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
                                 new SpeculationLog());
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
                 }
-                return addMethod(method, compResult, graphCopy);
+                return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable<InstalledCode>() {
+
+                    @Override
+                    public InstalledCode call() throws Exception {
+                        InstalledCode code = addMethod(method, compResult, graphCopy);
+                        if (Debug.isDumpEnabled()) {
+                            Debug.dump(new Object[]{compResult, code}, "After code installation");
+                        }
+
+                        return code;
+                    }
+                });
             }
         });
 
@@ -448,18 +459,7 @@
     }
 
     protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult, final StructuredGraph graph) {
-        return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable<InstalledCode>() {
-
-            @Override
-            public InstalledCode call() throws Exception {
-                InstalledCode installedCode = runtime.addMethod(method, compResult, graph);
-                if (Debug.isDumpEnabled()) {
-                    Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
-                }
-
-                return installedCode;
-            }
-        });
+        return runtime.addMethod(method, compResult, graph);
     }
 
     /**
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java	Thu May 23 14:44:01 2013 +0200
@@ -105,7 +105,7 @@
     }
 
     @Test
-    public void testTypeProfileInvokeVirtual() {
+    public void testProfileInvokeVirtual() {
         testTypeProfile("invokeVirtualSnippet", 1);
     }
 
@@ -140,18 +140,18 @@
         return obj instanceof Serializable;
     }
 
-    private void testTypeProfile(String methodName, int bci) {
+    private void testTypeProfile(String testSnippet, int bci) {
         ResolvedJavaType stringType = runtime.lookupJavaType(String.class);
         ResolvedJavaType stringBuilderType = runtime.lookupJavaType(StringBuilder.class);
 
-        ProfilingInfo info = profile(methodName, "ABC");
+        ProfilingInfo info = profile(testSnippet, "ABC");
         JavaTypeProfile typeProfile = info.getTypeProfile(bci);
         Assert.assertEquals(0.0, typeProfile.getNotRecordedProbability(), DELTA);
         Assert.assertEquals(1, typeProfile.getTypes().length);
         Assert.assertEquals(stringType, typeProfile.getTypes()[0].getType());
         Assert.assertEquals(1.0, typeProfile.getTypes()[0].getProbability(), DELTA);
 
-        continueProfiling(methodName, new StringBuilder());
+        continueProfiling(testSnippet, new StringBuilder());
         typeProfile = info.getTypeProfile(bci);
         Assert.assertEquals(0.0, typeProfile.getNotRecordedProbability(), DELTA);
         Assert.assertEquals(2, typeProfile.getTypes().length);
@@ -160,7 +160,7 @@
         Assert.assertEquals(0.5, typeProfile.getTypes()[0].getProbability(), DELTA);
         Assert.assertEquals(0.5, typeProfile.getTypes()[1].getProbability(), DELTA);
 
-        resetProfile(methodName);
+        resetProfile(testSnippet);
         typeProfile = info.getTypeProfile(bci);
         Assert.assertNull(typeProfile);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Thu May 23 14:44:01 2013 +0200
@@ -25,6 +25,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -95,7 +96,7 @@
                 for (FloatingReadNode node : graph.getNodes(LocalNode.class).first().usages().filter(FloatingReadNode.class)) {
                     // Checking that the parameter a is not directly used for the access to field
                     // x10 (because x10 must be guarded by the checkcast).
-                    Assert.assertTrue(node.location().getLocationIdentity() == LocationNode.FINAL_LOCATION);
+                    Assert.assertTrue(node.location().getLocationIdentity() == LocationIdentity.FINAL_LOCATION);
                 }
             }
         });
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java	Thu May 23 14:44:01 2013 +0200
@@ -33,7 +33,6 @@
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu May 23 14:44:01 2013 +0200
@@ -125,7 +125,8 @@
         } else {
             Debug.dump(graph, "initial state");
         }
-        new VerifyValueUsage(runtime).apply(graph);
+        new VerifyUsageWithEquals(runtime, Value.class).apply(graph);
+        new VerifyUsageWithEquals(runtime, Register.class).apply(graph);
 
         if (GraalOptions.OptCanonicalizer) {
             new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Thu May 23 14:44:01 2013 +0200
@@ -654,12 +654,12 @@
             int number = availableReg.number;
             if (usePos[number] >= intervalTo) {
                 // this register is free for the full interval
-                if (minFullReg == null || availableReg == hint || (usePos[number] < usePos[minFullReg.number] && minFullReg != hint)) {
+                if (minFullReg == null || availableReg.equals(hint) || (usePos[number] < usePos[minFullReg.number] && !minFullReg.equals(hint))) {
                     minFullReg = availableReg;
                 }
             } else if (usePos[number] > regNeededUntil) {
                 // this register is at least free until regNeededUntil
-                if (maxPartialReg == null || availableReg == hint || (usePos[number] > usePos[maxPartialReg.number] && maxPartialReg != hint)) {
+                if (maxPartialReg == null || availableReg.equals(hint) || (usePos[number] > usePos[maxPartialReg.number] && !maxPartialReg.equals(hint))) {
                     maxPartialReg = availableReg;
                 }
             }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Thu May 23 14:44:01 2013 +0200
@@ -53,7 +53,7 @@
             masm.movq(rbp, (AMD64Address) tasm.asAddress(savedRbp));
         } else {
             Register framePointer = asRegister(savedRbp);
-            if (framePointer != rbp) {
+            if (!framePointer.equals(rbp)) {
                 masm.movq(rbp, framePointer);
             }
         }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu May 23 14:44:01 2013 +0200
@@ -231,14 +231,16 @@
                 }
             }
         }
-        if (!hsLinkage.isLeaf()) {
-            append(new AMD64HotSpotCRuntimeCallPrologueOp());
-        }
 
-        Variable result = super.emitForeignCall(linkage, info, args);
+        Variable result;
 
         if (!hsLinkage.isLeaf()) {
+            assert info != null;
+            append(new AMD64HotSpotCRuntimeCallPrologueOp());
+            result = super.emitForeignCall(linkage, info, args);
             append(new AMD64HotSpotCRuntimeCallEpilogueOp());
+        } else {
+            result = super.emitForeignCall(linkage, null, args);
         }
 
         if (destroysRegisters) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Thu May 23 14:44:01 2013 +0200
@@ -24,15 +24,14 @@
 
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*;
-import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.DecryptBlockStubCall.*;
-import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.EncryptBlockStubCall.*;
-import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*;
-import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.EncryptAESCryptStubCall.*;
+import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.*;
+import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -62,14 +61,14 @@
         RegisterValue exception = rax.asValue(Kind.Object);
         RegisterValue exceptionPc = rdx.asValue(word);
         CallingConvention exceptionCc = new CallingConvention(0, ILLEGAL, exception, exceptionPc);
-        register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, exceptionCc));
-        register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, exceptionCc));
+        register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
+        register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
 
         // The x86 crypto stubs do callee saving
-        registerForeignCall(ENCRYPT_BLOCK, config.aescryptEncryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF);
-        registerForeignCall(DECRYPT_BLOCK, config.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF);
-        registerForeignCall(ENCRYPT, config.cipherBlockChainingEncryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF);
-        registerForeignCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF);
+        registerForeignCall(ENCRYPT_BLOCK, config.aescryptEncryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(DECRYPT_BLOCK, config.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(ENCRYPT, config.cipherBlockChainingEncryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
 
         convertSnippets = new AMD64ConvertSnippets.Templates(this, replacements, graalRuntime.getTarget());
         super.registerReplacements(replacements);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Thu May 23 14:44:01 2013 +0200
@@ -61,13 +61,13 @@
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
         tasm.recordMark(Marks.MARK_INLINE_INVOKE);
         Register callReg = asRegister(targetAddress);
-        assert callReg != METHOD;
+        assert !callReg.equals(METHOD);
         AMD64Call.indirectCall(tasm, masm, callReg, callTarget, state);
     }
 
     @Override
     protected void verify() {
         super.verify();
-        assert asRegister(metaspaceMethod) == METHOD;
+        assert asRegister(metaspaceMethod).equals(METHOD);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Thu May 23 14:44:01 2013 +0200
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.test;
+
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.security.*;
+
+import javax.crypto.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Tests the intrinsification of certain crypto methods.
+ */
+public class HotSpotCryptoSubstitutionTest extends GraalCompilerTest {
+
+    @Override
+    protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, StructuredGraph graph) {
+        HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
+        HotSpotNmethod installedCode = new HotSpotNmethod(hsMethod, graph, true);
+        HotSpotCompiledNmethod compiledNmethod = new HotSpotCompiledNmethod(hsMethod, StructuredGraph.INVOCATION_ENTRY_BCI, compResult);
+        CodeInstallResult result = graalRuntime().getCompilerToVM().installCode(compiledNmethod, installedCode, null);
+        Assert.assertEquals("Error installing method " + method + ": " + result, result, CodeInstallResult.OK);
+
+        // HotSpotRuntime hsRuntime = (HotSpotRuntime) runtime;
+        // TTY.println(hsMethod.toString());
+        // TTY.println(hsRuntime.disassemble(installedCode));
+        return installedCode;
+    }
+
+    @Test
+    public void testAESEncryptSubstitution() throws Exception {
+        byte[] seed = {0x4, 0x7, 0x1, 0x1};
+        SecureRandom random = new SecureRandom(seed);
+        KeyGenerator aesKeyGen = KeyGenerator.getInstance("AES");
+        aesKeyGen.init(128, random);
+        SecretKey aesKey = aesKeyGen.generateKey();
+        byte[] input = readClassfile16(getClass());
+
+        ByteArrayOutputStream expected = new ByteArrayOutputStream();
+        expected.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input));
+        expected.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input));
+
+        if (compiledAndInstall("com.sun.crypto.provider.AESCrypt", "encryptBlock", "decryptBlock")) {
+            ByteArrayOutputStream actual = new ByteArrayOutputStream();
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input));
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input));
+            Assert.assertArrayEquals(expected.toByteArray(), actual.toByteArray());
+        }
+
+        if (compiledAndInstall("com.sun.crypto.provider.CipherBlockChaining", "encrypt", "decrypt")) {
+            ByteArrayOutputStream actual = new ByteArrayOutputStream();
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input));
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input));
+            Assert.assertArrayEquals(expected.toByteArray(), actual.toByteArray());
+        }
+    }
+
+    /**
+     * Compiles and installs the substitution for some specified methods. Once installed, the next
+     * execution of the methods will use the newly installed code.
+     * 
+     * @param className the name of the class for which substitutions are available
+     * @param methodNames the names of the substituted methods
+     * @return true if at least one substitution was compiled and installed
+     */
+    private boolean compiledAndInstall(String className, String... methodNames) {
+        boolean atLeastOneCompiled = false;
+        for (String methodName : methodNames) {
+            Method method = lookup(className, methodName);
+            if (method != null) {
+                ResolvedJavaMethod installedCodeOwner = runtime.lookupJavaMethod(method);
+                StructuredGraph graph = replacements.getMethodSubstitution(installedCodeOwner);
+                if (graph != null) {
+                    Assert.assertNotNull(getCode(installedCodeOwner, graph, true));
+                    atLeastOneCompiled = true;
+                } else {
+                    Assert.assertFalse(graalRuntime().getConfig().useAESIntrinsics);
+                }
+            }
+        }
+        return atLeastOneCompiled;
+    }
+
+    private static Method lookup(String className, String methodName) {
+        Class c;
+        try {
+            c = Class.forName(className);
+            for (Method m : c.getDeclaredMethods()) {
+                if (m.getName().equals(methodName)) {
+                    return m;
+                }
+            }
+            // If the expected security provider exists, the specific method should also exist
+            throw new NoSuchMethodError(className + "." + methodName);
+        } catch (ClassNotFoundException e) {
+            // It's ok to not find the class - a different security provider
+            // may have been installed
+            return null;
+        }
+    }
+
+    AlgorithmParameters algorithmParameters;
+
+    private byte[] encrypt(byte[] indata, SecretKey key, String algorithm) throws Exception {
+
+        byte[] result = indata;
+
+        Cipher c = Cipher.getInstance(algorithm);
+        c.init(Cipher.ENCRYPT_MODE, key);
+        algorithmParameters = c.getParameters();
+
+        byte[] r1 = c.update(result);
+        byte[] r2 = c.doFinal();
+
+        result = new byte[r1.length + r2.length];
+        System.arraycopy(r1, 0, result, 0, r1.length);
+        System.arraycopy(r2, 0, result, r1.length, r2.length);
+
+        return result;
+    }
+
+    private byte[] decrypt(byte[] indata, SecretKey key, String algorithm) throws Exception {
+
+        byte[] result = indata;
+
+        Cipher c = Cipher.getInstance(algorithm);
+        c.init(Cipher.DECRYPT_MODE, key, algorithmParameters);
+
+        byte[] r1 = c.update(result);
+        byte[] r2 = c.doFinal();
+
+        result = new byte[r1.length + r2.length];
+        System.arraycopy(r1, 0, result, 0, r1.length);
+        System.arraycopy(r2, 0, result, r1.length, r2.length);
+        return result;
+    }
+
+    private static byte[] readClassfile16(Class c) throws IOException {
+        String classFilePath = "/" + c.getName().replace('.', '/') + ".class";
+        InputStream stream = c.getResourceAsStream(classFilePath);
+        int bytesToRead = stream.available();
+        bytesToRead -= bytesToRead % 16;
+        byte[] classFile = new byte[bytesToRead];
+        new DataInputStream(stream).readFully(classFile);
+        return classFile;
+    }
+
+    public byte[] runEncryptDecrypt(SecretKey key, String algorithm, byte[] input) throws Exception {
+        byte[] indata = input.clone();
+        byte[] cipher = encrypt(indata, key, algorithm);
+        byte[] plain = decrypt(cipher, key, algorithm);
+        Assert.assertArrayEquals(indata, plain);
+        return plain;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu May 23 14:44:01 2013 +0200
@@ -184,8 +184,10 @@
                 bailout.printStackTrace(TTY.cachedOut);
             }
         } catch (Throwable t) {
+            if (GraalOptions.PrintStackTraceOnException || GraalOptions.ExitVMOnException) {
+                t.printStackTrace(TTY.cachedOut);
+            }
             if (GraalOptions.ExitVMOnException) {
-                t.printStackTrace(TTY.cachedOut);
                 System.exit(-1);
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java	Thu May 23 14:44:01 2013 +0200
@@ -88,11 +88,18 @@
     private final Transition transition;
 
     /**
-     * The locations defined/killed by the call.
+     * The registers and stack slots defined/killed by the call.
      */
     private Value[] temporaries = AllocatableValue.NONE;
 
     /**
+     * The memory locations killed by the call.
+     */
+    private final LocationIdentity[] killedLocations;
+
+    private final boolean reexecutable;
+
+    /**
      * Creates a {@link HotSpotForeignCallLinkage}.
      * 
      * @param descriptor the descriptor of the call
@@ -101,10 +108,15 @@
      *            temporaries which are always destroyed)
      * @param ccType calling convention type
      * @param transition specifies if this is a {@linkplain #isLeaf() leaf} call
+     * @param reexecutable specifies if the call can be re-executed without (meaningful) side
+     *            effects. Deoptimization will not return to a point before a call that cannot be
+     *            re-executed.
+     * @param killedLocations the memory locations killed by the call
      */
-    public static HotSpotForeignCallLinkage create(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Type ccType, Transition transition) {
+    public static HotSpotForeignCallLinkage create(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Type ccType, Transition transition, boolean reexecutable,
+                    LocationIdentity... killedLocations) {
         CallingConvention targetCc = createCallingConvention(descriptor, ccType);
-        return new HotSpotForeignCallLinkage(descriptor, address, effect, transition, targetCc);
+        return new HotSpotForeignCallLinkage(descriptor, address, effect, transition, targetCc, reexecutable, killedLocations);
     }
 
     /**
@@ -130,12 +142,15 @@
         }
     }
 
-    public HotSpotForeignCallLinkage(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Transition transition, CallingConvention cc) {
+    public HotSpotForeignCallLinkage(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Transition transition, CallingConvention cc, boolean reexecutable,
+                    LocationIdentity... killedLocations) {
         this.address = address;
         this.effect = effect;
         this.transition = transition;
         this.descriptor = descriptor;
         this.cc = cc;
+        this.reexecutable = reexecutable;
+        this.killedLocations = killedLocations;
     }
 
     @Override
@@ -153,6 +168,14 @@
         return sb.toString();
     }
 
+    public boolean isReexecutable() {
+        return reexecutable;
+    }
+
+    public LocationIdentity[] getKilledLocations() {
+        return killedLocations;
+    }
+
     public CallingConvention getCallingConvention() {
         return cc;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu May 23 14:44:01 2013 +0200
@@ -226,6 +226,16 @@
     public int constMethodMaxStackOffset;
 
     /**
+     * Offset of _constants in a metaspace ConstMethod object.
+     */
+    public int constMethodConstantsOffset;
+
+    /**
+     * Offset of _pool_holder in a metaspace ConstantPool object.
+     */
+    public int constantPoolHolderOffset;
+
+    /**
      * Value of extra_stack_entries() in method.hpp.
      */
     public int extraStackEntries;
@@ -365,6 +375,7 @@
     public int dataLayoutCellSize;
     public int bciProfileWidth;
     public int typeProfileWidth;
+    public int methodProfileWidth;
 
     public long inlineCacheMissStub;
     public long handleDeoptStub;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Thu May 23 14:44:01 2013 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.FieldIntrospection.*;
+import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.JavaMethodProfile.ProfiledMethod;
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.hotspot.*;
@@ -204,6 +205,11 @@
         }
 
         @Override
+        public JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
+            return null;
+        }
+
+        @Override
         public double getBranchTakenProbability(HotSpotMethodData data, int position) {
             return -1;
         }
@@ -332,14 +338,14 @@
 
     private abstract static class AbstractTypeData extends CounterData {
 
-        private static final int RECEIVER_TYPE_DATA_ROW_SIZE = cellsToBytes(2);
-        private static final int RECEIVER_TYPE_DATA_SIZE = cellIndexToOffset(2) + RECEIVER_TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
-        protected static final int NONPROFILED_RECEIVER_COUNT_OFFSET = cellIndexToOffset(1);
-        private static final int RECEIVER_TYPE_DATA_FIRST_RECEIVER_OFFSET = cellIndexToOffset(2);
-        private static final int RECEIVER_TYPE_DATA_FIRST_COUNT_OFFSET = cellIndexToOffset(3);
+        protected static final int TYPE_DATA_ROW_SIZE = cellsToBytes(2);
 
-        protected AbstractTypeData(int tag) {
-            super(tag, RECEIVER_TYPE_DATA_SIZE);
+        protected static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(1);
+        protected static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(2);
+        protected static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(3);
+
+        protected AbstractTypeData(int tag, int staticSize) {
+            super(tag, staticSize);
         }
 
         @Override
@@ -352,10 +358,10 @@
             int entries = 0;
 
             for (int i = 0; i < typeProfileWidth; i++) {
-                long receiverKlass = data.readWord(position, getReceiverOffset(i));
+                long receiverKlass = data.readWord(position, getTypeOffset(i));
                 if (receiverKlass != 0) {
                     types[entries] = HotSpotResolvedObjectType.fromMetaspaceKlass(receiverKlass);
-                    long count = data.readUnsignedInt(position, getCountOffset(i));
+                    long count = data.readUnsignedInt(position, getTypeCountOffset(i));
                     totalCount += count;
                     counts[entries] = count;
 
@@ -390,21 +396,22 @@
             return new JavaTypeProfile(nullSeen, notRecordedTypeProbability, ptypes);
         }
 
-        private static int getReceiverOffset(int row) {
-            return RECEIVER_TYPE_DATA_FIRST_RECEIVER_OFFSET + row * RECEIVER_TYPE_DATA_ROW_SIZE;
+        private static int getTypeOffset(int row) {
+            return TYPE_DATA_FIRST_TYPE_OFFSET + row * TYPE_DATA_ROW_SIZE;
         }
 
-        protected static int getCountOffset(int row) {
-            return RECEIVER_TYPE_DATA_FIRST_COUNT_OFFSET + row * RECEIVER_TYPE_DATA_ROW_SIZE;
+        protected static int getTypeCountOffset(int row) {
+            return TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
         }
     }
 
     private static class TypeCheckData extends AbstractTypeData {
 
-        private static final int RECEIVER_TYPE_DATA_TAG = 4;
+        private static final int TYPE_CHECK_DATA_TAG = 4;
+        private static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
 
         public TypeCheckData() {
-            super(RECEIVER_TYPE_DATA_TAG);
+            super(TYPE_CHECK_DATA_TAG, TYPE_CHECK_DATA_SIZE);
         }
 
         @Override
@@ -414,16 +421,19 @@
 
         @Override
         protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
-            return data.readUnsignedIntAsSignedInt(position, NONPROFILED_RECEIVER_COUNT_OFFSET);
+            return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
         }
     }
 
     private static class VirtualCallData extends AbstractTypeData {
 
         private static final int VIRTUAL_CALL_DATA_TAG = 5;
+        private static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth);
+        private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+        private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
 
         public VirtualCallData() {
-            super(VIRTUAL_CALL_DATA_TAG);
+            super(VIRTUAL_CALL_DATA_TAG, VIRTUAL_CALL_DATA_SIZE);
         }
 
         @Override
@@ -432,7 +442,7 @@
 
             long total = 0;
             for (int i = 0; i < typeProfileWidth; i++) {
-                total += data.readUnsignedInt(position, getCountOffset(i));
+                total += data.readUnsignedInt(position, getTypeCountOffset(i));
             }
 
             total += getCounterValue(data, position);
@@ -443,6 +453,64 @@
         protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
             return getCounterValue(data, position);
         }
+
+        private static long getMethodsNotRecordedExecutionCount(HotSpotMethodData data, int position) {
+            return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
+        }
+
+        @Override
+        public JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
+            int profileWidth = config.methodProfileWidth;
+
+            ResolvedJavaMethod[] methods = new ResolvedJavaMethod[profileWidth];
+            long[] counts = new long[profileWidth];
+            long totalCount = 0;
+            int entries = 0;
+
+            for (int i = 0; i < profileWidth; i++) {
+                long method = data.readWord(position, getMethodOffset(i));
+                if (method != 0) {
+                    methods[entries] = HotSpotResolvedJavaMethod.fromMetaspace(method);
+                    long count = data.readUnsignedInt(position, getMethodCountOffset(i));
+                    totalCount += count;
+                    counts[entries] = count;
+
+                    entries++;
+                }
+            }
+
+            totalCount += getMethodsNotRecordedExecutionCount(data, position);
+            return createMethodProfile(methods, counts, totalCount, entries);
+        }
+
+        private static JavaMethodProfile createMethodProfile(ResolvedJavaMethod[] methods, long[] counts, long totalCount, int entries) {
+            if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) {
+                return null;
+            }
+
+            ProfiledMethod[] pmethods = new ProfiledMethod[entries];
+            double totalProbability = 0.0;
+            for (int i = 0; i < entries; i++) {
+                double p = counts[i];
+                p = p / totalCount;
+                totalProbability += p;
+                pmethods[i] = new ProfiledMethod(methods[i], p);
+            }
+
+            Arrays.sort(pmethods);
+
+            double notRecordedMethodProbability = entries < config.methodProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability));
+            assert notRecordedMethodProbability == 0 || entries == config.methodProfileWidth;
+            return new JavaMethodProfile(notRecordedMethodProbability, pmethods);
+        }
+
+        private static int getMethodOffset(int row) {
+            return VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        }
+
+        private static int getMethodCountOffset(int row) {
+            return VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        }
     }
 
     private static class RetData extends CounterData {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java	Thu May 23 14:44:01 2013 +0200
@@ -55,6 +55,8 @@
 
     JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position);
 
+    JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position);
+
     double getBranchTakenProbability(HotSpotMethodData data, int position);
 
     double[] getSwitchProbabilities(HotSpotMethodData data, int position);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java	Thu May 23 14:44:01 2013 +0200
@@ -57,6 +57,12 @@
     }
 
     @Override
+    public JavaMethodProfile getMethodProfile(int bci) {
+        findBCI(bci, false);
+        return dataAccessor.getMethodProfile(methodData, position);
+    }
+
+    @Override
     public double getBranchTakenProbability(int bci) {
         findBCI(bci, false);
         return dataAccessor.getBranchTakenProbability(methodData, position);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Thu May 23 14:44:01 2013 +0200
@@ -31,7 +31,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu May 23 14:44:01 2013 +0200
@@ -66,6 +66,35 @@
     private CompilationTask currentTask;
     private SpeculationLog speculationLog;
 
+    /**
+     * Gets the holder of a HotSpot metaspace method native object.
+     * 
+     * @param metaspaceMethod a metaspace Method object
+     * @return the {@link ResolvedJavaType} corresponding to the holder of the
+     *         {@code metaspaceMethod}
+     */
+    public static HotSpotResolvedObjectType getHolder(long metaspaceMethod) {
+        HotSpotVMConfig config = graalRuntime().getConfig();
+        long constMethod = unsafe.getLong(metaspaceMethod + config.methodConstMethodOffset);
+        assert constMethod != 0;
+        long constantPool = unsafe.getLong(constMethod + config.constMethodConstantsOffset);
+        assert constantPool != 0;
+        long holder = unsafe.getLong(constantPool + config.constantPoolHolderOffset);
+        assert holder != 0;
+        return (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromMetaspaceKlass(holder);
+    }
+
+    /**
+     * Gets the {@link ResolvedJavaMethod} for a HotSpot metaspace method native object.
+     * 
+     * @param metaspaceMethod a metaspace Method object
+     * @return the {@link ResolvedJavaMethod} corresponding to {@code metaspaceMethod}
+     */
+    public static HotSpotResolvedJavaMethod fromMetaspace(long metaspaceMethod) {
+        HotSpotResolvedObjectType holder = getHolder(metaspaceMethod);
+        return holder.createMethod(metaspaceMethod);
+    }
+
     HotSpotResolvedJavaMethod(HotSpotResolvedObjectType holder, long metaspaceMethod) {
         this.metaspaceMethod = metaspaceMethod;
         this.holder = holder;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu May 23 14:44:01 2013 +0200
@@ -26,22 +26,23 @@
 import static com.oracle.graal.api.code.DeoptimizationAction.*;
 import static com.oracle.graal.api.code.MemoryBarriers.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*;
 import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*;
-import static com.oracle.graal.hotspot.nodes.ThreadIsInterruptedStubCall.*;
 import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
-import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*;
 import static com.oracle.graal.hotspot.nodes.WriteBarrierPostStubCall.*;
 import static com.oracle.graal.hotspot.nodes.WriteBarrierPreStubCall.*;
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*;
 import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
+import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*;
 import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*;
 import static com.oracle.graal.hotspot.stubs.NewArrayStub.*;
 import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
@@ -95,6 +96,7 @@
 
     public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class);
     public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class);
+    public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class);
 
     public final HotSpotVMConfig config;
 
@@ -190,18 +192,29 @@
 
     /**
      * Creates and registers the details for linking a foreign call to a {@link Stub}.
+     * 
+     * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side
+     *            effects. Deoptimization will not return to a point before a stub call that cannot
+     *            be re-executed.
+     * @param killedLocations the memory locations killed by the stub call
      */
-    protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor) {
-        return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF));
+    protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, LocationIdentity... killedLocations) {
+        return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF, reexecutable, killedLocations));
     }
 
     /**
      * Creates and registers the linkage for a foreign call.
+     * 
+     * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side
+     *            effects. Deoptimization will not return to a point before a stub call that cannot
+     *            be re-executed.
+     * @param killedLocations the memory locations killed by the stub call
      */
-    protected HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type ccType, RegisterEffect effect, Transition transition) {
+    protected HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type ccType, RegisterEffect effect, Transition transition,
+                    boolean reexecutable, LocationIdentity... killedLocations) {
         Class<?> resultType = descriptor.getResultType();
         assert resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "foreign calls must return objects in thread local storage: " + descriptor;
-        return register(HotSpotForeignCallLinkage.create(descriptor, address, effect, ccType, transition));
+        return register(HotSpotForeignCallLinkage.create(descriptor, address, effect, ccType, transition, reexecutable, killedLocations));
     }
 
     private static void link(Stub stub) {
@@ -215,9 +228,13 @@
      * @param address the address of the code to call
      * @param prependThread true if the JavaThread value for the current thread is to be prepended
      *            to the arguments for the call to {@code address}
+     * @param reexecutable specifies if the foreign call can be re-executed without (meaningful)
+     *            side effects. Deoptimization will not return to a point before a foreign call that
+     *            cannot be re-executed.
+     * @param killedLocations the memory locations killed by the foreign call
      */
-    private void linkForeignCall(ForeignCallDescriptor descriptor, long address, boolean prependThread, Replacements replacements) {
-        ForeignCallStub stub = new ForeignCallStub(address, descriptor, prependThread, this, replacements);
+    private void linkForeignCall(Replacements replacements, ForeignCallDescriptor descriptor, long address, boolean prependThread, boolean reexecutable, LocationIdentity... killedLocations) {
+        ForeignCallStub stub = new ForeignCallStub(this, replacements, address, descriptor, prependThread, reexecutable, killedLocations);
         HotSpotForeignCallLinkage linkage = stub.getLinkage();
         HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage();
         linkage.setCompiledStub(stub);
@@ -225,78 +242,86 @@
         register(targetLinkage);
     }
 
-    public void registerReplacements(Replacements replacements) {
+    public static final boolean PREPEND_THREAD = true;
+    public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD;
+
+    public static final boolean REEXECUTABLE = true;
+    public static final boolean NOT_REEXECUTABLE = !REEXECUTABLE;
+
+    public static final LocationIdentity[] NO_LOCATIONS = {};
+
+    public void registerReplacements(Replacements r) {
         HotSpotVMConfig c = config;
         TargetDescription target = getTarget();
 
-        registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF);
-        registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF);
-        registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF);
+        registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
 
-        registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF);
-        registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF);
-        registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF);
-        registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF);
-        registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF);
+        registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
 
-        registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF);
-        registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF);
-        registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF);
-        registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF);
-        registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF);
+        registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
 
-        link(new NewInstanceStub(this, replacements, target, registerStubCall(NEW_INSTANCE)));
-        link(new NewArrayStub(this, replacements, target, registerStubCall(NEW_ARRAY)));
-        link(new ExceptionHandlerStub(this, replacements, target, foreignCalls.get(EXCEPTION_HANDLER)));
-        link(new UnwindExceptionToCallerStub(this, replacements, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER)));
-        link(new VerifyOopStub(this, replacements, target, registerStubCall(VERIFY_OOP)));
+        link(new NewInstanceStub(this, r, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, ANY_LOCATION)));
+        link(new NewArrayStub(this, r, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, ANY_LOCATION)));
+        link(new ExceptionHandlerStub(this, r, target, foreignCalls.get(EXCEPTION_HANDLER)));
+        link(new UnwindExceptionToCallerStub(this, r, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, ANY_LOCATION)));
+        link(new VerifyOopStub(this, r, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, NO_LOCATIONS)));
 
-        linkForeignCall(IDENTITY_HASHCODE, c.identityHashCodeAddress, true, replacements);
-        linkForeignCall(REGISTER_FINALIZER, c.registerFinalizerAddress, true, replacements);
-        linkForeignCall(CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, true, replacements);
-        linkForeignCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, true, replacements);
-        linkForeignCall(MONITORENTER, c.monitorenterAddress, true, replacements);
-        linkForeignCall(MONITOREXIT, c.monitorexitAddress, true, replacements);
-        linkForeignCall(WRITE_BARRIER_PRE, c.writeBarrierPreAddress, true, replacements);
-        linkForeignCall(WRITE_BARRIER_POST, c.writeBarrierPostAddress, true, replacements);
-        linkForeignCall(NEW_MULTI_ARRAY, c.newMultiArrayAddress, true, replacements);
-        linkForeignCall(LOG_PRINTF, c.logPrintfAddress, true, replacements);
-        linkForeignCall(LOG_OBJECT, c.logObjectAddress, true, replacements);
-        linkForeignCall(LOG_PRIMITIVE, c.logPrimitiveAddress, true, replacements);
-        linkForeignCall(THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, true, replacements);
-        linkForeignCall(VM_ERROR, c.vmErrorAddress, true, replacements);
-        linkForeignCall(OSR_MIGRATION_END, c.osrMigrationEndAddress, false, replacements);
+        linkForeignCall(r, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_REEXECUTABLE, MARK_WORD_LOCATION);
+        linkForeignCall(r, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, PREPEND_THREAD, REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, PREPEND_THREAD, REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, WRITE_BARRIER_PRE, c.writeBarrierPreAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, WRITE_BARRIER_POST, c.writeBarrierPostAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(r, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(r, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(r, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(r, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, NOT_REEXECUTABLE, NO_LOCATIONS);
 
         if (GraalOptions.IntrinsifyObjectMethods) {
-            replacements.registerSubstitutions(ObjectSubstitutions.class);
+            r.registerSubstitutions(ObjectSubstitutions.class);
         }
         if (GraalOptions.IntrinsifySystemMethods) {
-            replacements.registerSubstitutions(SystemSubstitutions.class);
+            r.registerSubstitutions(SystemSubstitutions.class);
         }
         if (GraalOptions.IntrinsifyThreadMethods) {
-            replacements.registerSubstitutions(ThreadSubstitutions.class);
+            r.registerSubstitutions(ThreadSubstitutions.class);
         }
         if (GraalOptions.IntrinsifyUnsafeMethods) {
-            replacements.registerSubstitutions(UnsafeSubstitutions.class);
+            r.registerSubstitutions(UnsafeSubstitutions.class);
         }
         if (GraalOptions.IntrinsifyClassMethods) {
-            replacements.registerSubstitutions(ClassSubstitutions.class);
+            r.registerSubstitutions(ClassSubstitutions.class);
         }
         if (GraalOptions.IntrinsifyAESMethods) {
-            replacements.registerSubstitutions(AESCryptSubstitutions.class);
-            replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class);
+            r.registerSubstitutions(AESCryptSubstitutions.class);
+            r.registerSubstitutions(CipherBlockChainingSubstitutions.class);
         }
         if (GraalOptions.IntrinsifyReflectionMethods) {
-            replacements.registerSubstitutions(ReflectionSubstitutions.class);
+            r.registerSubstitutions(ReflectionSubstitutions.class);
         }
 
-        checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, graalRuntime.getTarget());
-        instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, graalRuntime.getTarget());
-        newObjectSnippets = new NewObjectSnippets.Templates(this, replacements, graalRuntime.getTarget());
-        monitorSnippets = new MonitorSnippets.Templates(this, replacements, graalRuntime.getTarget(), c.useFastLocking);
-        writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, replacements, graalRuntime.getTarget());
-        boxingSnippets = new BoxingSnippets.Templates(this, replacements, graalRuntime.getTarget());
-        exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, replacements, graalRuntime.getTarget());
+        checkcastSnippets = new CheckCastSnippets.Templates(this, r, graalRuntime.getTarget());
+        instanceofSnippets = new InstanceOfSnippets.Templates(this, r, graalRuntime.getTarget());
+        newObjectSnippets = new NewObjectSnippets.Templates(this, r, graalRuntime.getTarget());
+        monitorSnippets = new MonitorSnippets.Templates(this, r, graalRuntime.getTarget(), c.useFastLocking);
+        writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, r, graalRuntime.getTarget());
+        boxingSnippets = new BoxingSnippets.Templates(this, r, graalRuntime.getTarget());
+        exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, r, graalRuntime.getTarget());
     }
 
     public HotSpotGraalRuntime getGraalRuntime() {
@@ -449,7 +474,7 @@
         if (n instanceof ArrayLengthNode) {
             ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n;
             ValueNode array = arrayLengthNode.array();
-            ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(LocationNode.FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt()));
+            ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt()));
             tool.createNullCheckGuard(arrayLengthRead, array);
             graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead);
         } else if (n instanceof Invoke) {
@@ -476,7 +501,7 @@
                             // We use LocationNode.ANY_LOCATION for the reads that access the
                             // compiled code entry as HotSpot does not guarantee they are final
                             // values.
-                            ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph),
+                            ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph),
                                             StampFactory.forKind(wordKind())));
 
                             loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
@@ -532,7 +557,7 @@
         } else if (n instanceof CompareAndSwapNode) {
             // Separate out GC barrier semantics
             CompareAndSwapNode cas = (CompareAndSwapNode) n;
-            LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1);
+            LocationNode location = IndexedLocationNode.create(ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1);
             cas.setLocation(location);
             cas.setWriteBarrierType(getCompareAndSwapBarrier(cas));
         } else if (n instanceof LoadIndexedNode) {
@@ -562,7 +587,7 @@
                     }
                 } else {
                     LoadHubNode arrayClass = graph.add(new LoadHubNode(array, wordKind));
-                    LocationNode location = ConstantLocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph);
+                    LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph);
                     FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind())));
                     CheckCastDynamicNode checkcast = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true));
                     graph.addBeforeFixed(storeIndexed, checkcast);
@@ -579,7 +604,7 @@
         } else if (n instanceof UnsafeLoadNode) {
             UnsafeLoadNode load = (UnsafeLoadNode) n;
             assert load.kind() != Kind.Illegal;
-            IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1);
+            IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1);
             ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp()));
             // An unsafe read must not floating outside its block as may float above an explicit
             // null check on its object.
@@ -587,7 +612,7 @@
             graph.replaceFixedWithFixed(load, memoryRead);
         } else if (n instanceof UnsafeStoreNode) {
             UnsafeStoreNode store = (UnsafeStoreNode) n;
-            IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1);
+            IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1);
             ValueNode object = store.object();
             WriteBarrierType barrierType = getUnsafeStoreBarrierType(store);
             WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType));
@@ -683,8 +708,8 @@
             OSRStartNode osrStart = (OSRStartNode) n;
             StartNode newStart = graph.add(new StartNode());
             LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind())));
-            ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(OSR_MIGRATION_END, buffer));
-            newStart.setStateAfter(osrStart.stateAfter());
+            ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(this, OSR_MIGRATION_END, buffer));
+            migrationEnd.setStateAfter(osrStart.stateAfter());
 
             newStart.setNext(migrationEnd);
             FixedNode next = osrStart.next();
@@ -749,12 +774,12 @@
         assert vtableEntryOffset > 0;
         // We use LocationNode.ANY_LOCATION for the reads that access the vtable
         // entry as HotSpot does not guarantee that this is a final value.
-        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(LocationNode.ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind())));
+        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind())));
         return metaspaceMethod;
     }
 
     private ReadNode createReadHub(LoweringTool tool, StructuredGraph graph, Kind wordKind, ValueNode object) {
-        LocationNode location = ConstantLocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.hubOffset, graph);
+        LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
         ReadNode hub = graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind())));
         tool.createNullCheckGuard(hub, object);
@@ -809,7 +834,7 @@
 
     protected IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) {
         int scale = this.graalRuntime.getTarget().arch.getSizeInBytes(elementKind);
-        return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale);
+        return IndexedLocationNode.create(NamedLocationIdentity.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale);
     }
 
     private static GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) {
@@ -967,12 +992,12 @@
     }
 
     @Override
-    public boolean hasSideEffect(ForeignCallDescriptor descriptor) {
-        // Only these two foreign calls are expected to be made with
-        // a node that implements StateSplit. They need to be a state
-        // split so that the stack trace they produce is accurate.
-        assert descriptor == CREATE_NULL_POINTER_EXCEPTION || descriptor == CREATE_OUT_OF_BOUNDS_EXCEPTION : descriptor;
-        return false;
+    public boolean isReexecutable(ForeignCallDescriptor descriptor) {
+        return foreignCalls.get(descriptor).isReexecutable();
+    }
+
+    public LocationIdentity[] getKilledLocationIdentities(ForeignCallDescriptor descriptor) {
+        return foreignCalls.get(descriptor).getKilledLocations();
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
@@ -29,7 +31,6 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 
@@ -55,7 +56,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.word.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,11 +22,13 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.type.*;
 
 /**
@@ -46,7 +48,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java	Thu May 23 14:44:01 2013 +0200
@@ -30,7 +30,6 @@
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -49,7 +48,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{LocationIdentity.ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Fri May 17 16:47:13 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.nodes;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.word.*;
-
-/**
- * Node implementing a call to {@code GraalRuntime::monitorenter}.
- */
-public class MonitorEnterStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
-
-    @Input private ValueNode object;
-    @Input private ValueNode lock;
-    public static final ForeignCallDescriptor MONITORENTER = new ForeignCallDescriptor("monitorenter", void.class, Object.class, Word.class);
-
-    public MonitorEnterStubCall(ValueNode object, ValueNode lock) {
-        super(StampFactory.forVoid());
-        this.object = object;
-        this.lock = lock;
-    }
-
-    @Override
-    public void generate(LIRGenerator gen) {
-        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(MONITORENTER);
-        gen.emitForeignCall(linkage, this, gen.operand(object), gen.operand(lock));
-    }
-
-    @NodeIntrinsic
-    public static native void call(Object object, Word lock);
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Thu May 23 14:44:01 2013 +0200
@@ -43,8 +43,8 @@
 
     public static final ForeignCallDescriptor NEW_MULTI_ARRAY = new ForeignCallDescriptor("new_multi_array", Object.class, Word.class, int.class, Word.class);
 
-    public NewMultiArrayStubCall(ValueNode hub, int rank, ValueNode dims) {
-        super(NEW_MULTI_ARRAY, defaultStamp);
+    public NewMultiArrayStubCall(MetaAccessProvider runtime, ValueNode hub, int rank, ValueNode dims) {
+        super(runtime, NEW_MULTI_ARRAY, defaultStamp);
         this.hub = hub;
         this.rank = rank;
         this.dims = dims;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java	Fri May 17 16:47:13 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.nodes;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * Node implementing a call to {@code GraalRuntime::thread_is_interrupted}.
- */
-public class ThreadIsInterruptedStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
-
-    @Input private ValueNode thread;
-    @Input private ValueNode clearIsInterrupted;
-    public static final ForeignCallDescriptor THREAD_IS_INTERRUPTED = new ForeignCallDescriptor("thread_is_interrupted", boolean.class, Object.class, boolean.class);
-
-    public ThreadIsInterruptedStubCall(ValueNode thread, ValueNode clearIsInterrupted) {
-        super(StampFactory.forInteger(Kind.Int, 0, 1));
-        this.thread = thread;
-        this.clearIsInterrupted = clearIsInterrupted;
-    }
-
-    @Override
-    public void generate(LIRGenerator gen) {
-        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(ThreadIsInterruptedStubCall.THREAD_IS_INTERRUPTED);
-        Variable result = gen.emitForeignCall(linkage, this, gen.operand(thread), gen.operand(clearIsInterrupted));
-        gen.setResult(this, result);
-    }
-
-    @NodeIntrinsic
-    public static boolean call(Thread thread, boolean clearIsInterrupted) {
-        try {
-            Method isInterrupted = Thread.class.getDeclaredMethod("isInterrupted", boolean.class);
-            isInterrupted.setAccessible(true);
-            return (Boolean) isInterrupted.invoke(thread, clearIsInterrupted);
-        } catch (Exception e) {
-            throw new GraalInternalError(e);
-        }
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Fri May 17 16:47:13 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.nodes;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.stubs.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * Call to {@link VerifyOopStub}.
- */
-public class VerifyOopStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
-
-    @Input private ValueNode object;
-    public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class);
-
-    public VerifyOopStubCall(ValueNode object) {
-        super(StampFactory.objectNonNull());
-        this.object = object;
-    }
-
-    @Override
-    public void generate(LIRGenerator gen) {
-        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(VerifyOopStubCall.VERIFY_OOP);
-        gen.emitForeignCall(linkage, this, gen.operand(object));
-    }
-
-    @NodeIntrinsic
-    public static native Object call(Object object);
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Thu May 23 14:44:01 2013 +0200
@@ -22,18 +22,17 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import sun.misc.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -72,56 +71,18 @@
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
         if (encrypt) {
-            EncryptBlockStubCall.call(inAddr, outAddr, kAddr);
+            encryptBlockStub(ENCRYPT_BLOCK, inAddr, outAddr, kAddr);
         } else {
-            DecryptBlockStubCall.call(inAddr, outAddr, kAddr);
+            decryptBlockStub(DECRYPT_BLOCK, inAddr, outAddr, kAddr);
         }
     }
 
-    abstract static class CryptBlockStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
-
-        @Input private ValueNode in;
-        @Input private ValueNode out;
-        @Input private ValueNode key;
-
-        private final ForeignCallDescriptor descriptor;
-
-        public CryptBlockStubCall(ValueNode in, ValueNode out, ValueNode key, ForeignCallDescriptor descriptor) {
-            super(StampFactory.forVoid());
-            this.in = in;
-            this.out = out;
-            this.key = key;
-            this.descriptor = descriptor;
-        }
-
-        @Override
-        public void generate(LIRGenerator gen) {
-            ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(descriptor);
-            gen.emitForeignCall(linkage, null, gen.operand(in), gen.operand(out), gen.operand(key));
-        }
-    }
+    public static final ForeignCallDescriptor ENCRYPT_BLOCK = new ForeignCallDescriptor("encrypt_block", void.class, Word.class, Word.class, Word.class);
+    public static final ForeignCallDescriptor DECRYPT_BLOCK = new ForeignCallDescriptor("decrypt_block", void.class, Word.class, Word.class, Word.class);
 
-    public static class EncryptBlockStubCall extends CryptBlockStubCall {
-
-        public static final ForeignCallDescriptor ENCRYPT_BLOCK = new ForeignCallDescriptor("encrypt_block", void.class, Word.class, Word.class, Word.class);
-
-        public EncryptBlockStubCall(ValueNode in, ValueNode out, ValueNode key) {
-            super(in, out, key, ENCRYPT_BLOCK);
-        }
-
-        @NodeIntrinsic
-        public static native void call(Word in, Word out, Word key);
-    }
+    @NodeIntrinsic(ForeignCallNode.class)
+    public static native void encryptBlockStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key);
 
-    public static class DecryptBlockStubCall extends CryptBlockStubCall {
-
-        public static final ForeignCallDescriptor DECRYPT_BLOCK = new ForeignCallDescriptor("decrypt_block", void.class, Word.class, Word.class, Word.class);
-
-        public DecryptBlockStubCall(ValueNode in, ValueNode out, ValueNode key) {
-            super(in, out, key, DECRYPT_BLOCK);
-        }
-
-        @NodeIntrinsic
-        public static native void call(Word in, Word out, Word key);
-    }
+    @NodeIntrinsic(ForeignCallNode.class)
+    public static native void decryptBlockStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Thu May 23 14:44:01 2013 +0200
@@ -273,9 +273,20 @@
             ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]);
             callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType);
         }
+        graph().add(callTarget);
 
-        graph().add(callTarget);
-        InvokeNode invoke = graph().add(new InvokeNode(callTarget, getBci()));
+        // The call target can have a different return type than the invoker,
+        // e.g. the target returns an Object but the invoker void. In this case
+        // we need to use the stamp of the invoker. Note: always using the
+        // invoker's stamp would be wrong because it's a less concrete type
+        // (usually java.lang.Object).
+        InvokeNode invoke;
+        if (callTarget.returnStamp().kind() != stamp().kind()) {
+            invoke = new InvokeNode(callTarget, getBci(), stamp());
+        } else {
+            invoke = new InvokeNode(callTarget, getBci());
+        }
+        graph().add(invoke);
         invoke.setStateAfter(stateAfter());
         return invoke;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Thu May 23 14:44:01 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Thu May 23 14:44:01 2013 +0200
@@ -31,6 +31,7 @@
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.meta.*;
@@ -94,7 +95,7 @@
             isNull.inc();
         } else {
             Word objectHub = loadHub(object);
-            if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) {
+            if (objectHub.readWord(superCheckOffset, LocationIdentity.FINAL_LOCATION).notEqual(hub)) {
                 displayMiss.inc();
                 DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
             }
@@ -187,7 +188,7 @@
                 args = new Arguments(secondary);
                 args.add("hub", hub);
                 args.add("object", object);
-                args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints);
+                args.addVarargs("hints", Word.class, StampFactory.forKind(getWordKind()), hints);
             }
             args.addConst("checkNull", !object.stamp().nonNull());
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Thu May 23 14:44:01 2013 +0200
@@ -22,18 +22,17 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import sun.misc.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.word.*;
 
@@ -72,19 +71,6 @@
         }
     }
 
-    private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) {
-        Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
-        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
-        Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
-        Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
-        if (encrypt) {
-            EncryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength);
-        } else {
-            DecryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength);
-        }
-
-    }
-
     @MethodSubstitution(isStatic = false)
     static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
         Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), ANY_LOCATION);
@@ -95,54 +81,24 @@
         }
     }
 
-    abstract static class AESCryptStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
-
-        @Input private ValueNode in;
-        @Input private ValueNode out;
-        @Input private ValueNode key;
-        @Input private ValueNode r;
-        @Input private ValueNode inLength;
-
-        private final ForeignCallDescriptor descriptor;
-
-        public AESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength, ForeignCallDescriptor descriptor) {
-            super(StampFactory.forVoid());
-            this.in = in;
-            this.out = out;
-            this.key = key;
-            this.r = r;
-            this.inLength = inLength;
-            this.descriptor = descriptor;
-        }
-
-        @Override
-        public void generate(LIRGenerator gen) {
-            ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(descriptor);
-            gen.emitForeignCall(linkage, null, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength));
+    private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) {
+        Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
+        Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
+        if (encrypt) {
+            encryptAESCryptStub(ENCRYPT, inAddr, outAddr, kAddr, rAddr, inLength);
+        } else {
+            decryptAESCryptStub(DECRYPT, inAddr, outAddr, kAddr, rAddr, inLength);
         }
     }
 
-    public static class EncryptAESCryptStubCall extends AESCryptStubCall {
-
-        public static final ForeignCallDescriptor ENCRYPT = new ForeignCallDescriptor("encrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class);
-
-        public EncryptAESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength) {
-            super(in, out, key, r, inLength, ENCRYPT);
-        }
-
-        @NodeIntrinsic
-        public static native void call(Word in, Word out, Word key, Word r, int inLength);
-    }
+    public static final ForeignCallDescriptor ENCRYPT = new ForeignCallDescriptor("encrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class);
+    public static final ForeignCallDescriptor DECRYPT = new ForeignCallDescriptor("decrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class);
 
-    public static class DecryptAESCryptStubCall extends AESCryptStubCall {
-
-        public static final ForeignCallDescriptor DECRYPT = new ForeignCallDescriptor("decrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class);
+    @NodeIntrinsic(ForeignCallNode.class)
+    public static native void encryptAESCryptStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key, Word r, int inLength);
 
-        public DecryptAESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength) {
-            super(in, out, key, r, inLength, DECRYPT);
-        }
-
-        @NodeIntrinsic
-        public static native void call(Word in, Word out, Word key, Word r, int inLength);
-    }
+    @NodeIntrinsic(ForeignCallNode.class)
+    public static native void decryptAESCryptStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key, Word r, int inLength);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Thu May 23 14:44:01 2013 +0200
@@ -27,6 +27,7 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.word.*;
@@ -44,7 +45,7 @@
             // Class for primitive type
             return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
         } else {
-            return klass.readInt(klassModifierFlagsOffset(), FINAL_LOCATION);
+            return klass.readInt(klassModifierFlagsOffset(), LocationIdentity.FINAL_LOCATION);
         }
     }
 
@@ -54,7 +55,7 @@
         if (klass.equal(0)) {
             return false;
         } else {
-            int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION);
+            int accessFlags = klass.readInt(klassAccessFlagsOffset(), LocationIdentity.FINAL_LOCATION);
             return (accessFlags & Modifier.INTERFACE) != 0;
         }
     }
@@ -79,16 +80,16 @@
     public static Class<?> getSuperclass(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
         if (klass.notEqual(0)) {
-            int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION);
+            int accessFlags = klass.readInt(klassAccessFlagsOffset(), LocationIdentity.FINAL_LOCATION);
             if ((accessFlags & Modifier.INTERFACE) == 0) {
                 if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) {
                     return Object.class;
                 } else {
-                    Word superKlass = klass.readWord(klassSuperKlassOffset(), FINAL_LOCATION);
+                    Word superKlass = klass.readWord(klassSuperKlassOffset(), LocationIdentity.FINAL_LOCATION);
                     if (superKlass.equal(0)) {
                         return null;
                     } else {
-                        return unsafeCast(superKlass.readObject(classMirrorOffset(), FINAL_LOCATION), Class.class, true, true);
+                        return unsafeCast(superKlass.readObject(classMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
                     }
                 }
             }
@@ -101,7 +102,7 @@
         Word klass = loadWordFromObject(thisObj, klassOffset());
         if (klass.notEqual(0)) {
             if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) {
-                return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), FINAL_LOCATION), Class.class, true, true);
+                return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
             }
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Thu May 23 14:44:01 2013 +0200
@@ -33,9 +33,7 @@
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
@@ -47,9 +45,6 @@
  */
 public class HotSpotReplacementsUtil {
 
-    public static final LocationIdentity ANY_LOCATION = LocationNode.ANY_LOCATION;
-    public static final LocationIdentity FINAL_LOCATION = LocationNode.FINAL_LOCATION;
-
     public static HotSpotVMConfig config() {
         return graalRuntime().getConfig();
     }
@@ -64,7 +59,7 @@
         return config().verifyOops;
     }
 
-    public static final LocationIdentity EXCEPTION_OOP_LOCATION = LocationNode.createLocation("ExceptionOop");
+    public static final LocationIdentity EXCEPTION_OOP_LOCATION = new NamedLocationIdentity("ExceptionOop");
 
     /**
      * @see HotSpotVMConfig#threadExceptionOopOffset
@@ -74,35 +69,35 @@
         return config().threadExceptionOopOffset;
     }
 
-    public static final LocationIdentity EXCEPTION_PC_LOCATION = LocationNode.createLocation("ExceptionPc");
+    public static final LocationIdentity EXCEPTION_PC_LOCATION = new NamedLocationIdentity("ExceptionPc");
 
     @Fold
     public static int threadExceptionPcOffset() {
         return config().threadExceptionPcOffset;
     }
 
-    public static final LocationIdentity TLAB_TOP_LOCATION = LocationNode.createLocation("TlabTop");
+    public static final LocationIdentity TLAB_TOP_LOCATION = new NamedLocationIdentity("TlabTop");
 
     @Fold
     public static int threadTlabTopOffset() {
         return config().threadTlabTopOffset;
     }
 
-    public static final LocationIdentity TLAB_END_LOCATION = LocationNode.createLocation("TlabEnd");
+    public static final LocationIdentity TLAB_END_LOCATION = new NamedLocationIdentity("TlabEnd");
 
     @Fold
     private static int threadTlabEndOffset() {
         return config().threadTlabEndOffset;
     }
 
-    public static final LocationIdentity TLAB_START_LOCATION = LocationNode.createLocation("TlabStart");
+    public static final LocationIdentity TLAB_START_LOCATION = new NamedLocationIdentity("TlabStart");
 
     @Fold
     private static int threadTlabStartOffset() {
         return config().threadTlabStartOffset;
     }
 
-    public static final LocationIdentity PENDING_EXCEPTION_LOCATION = LocationNode.createLocation("PendingException");
+    public static final LocationIdentity PENDING_EXCEPTION_LOCATION = new NamedLocationIdentity("PendingException");
 
     /**
      * @see HotSpotVMConfig#pendingExceptionOffset
@@ -112,7 +107,7 @@
         return config().pendingExceptionOffset;
     }
 
-    public static final LocationIdentity OBJECT_RESULT_LOCATION = LocationNode.createLocation("ObjectResult");
+    public static final LocationIdentity OBJECT_RESULT_LOCATION = new NamedLocationIdentity("ObjectResult");
 
     @Fold
     private static int objectResultOffset() {
@@ -201,7 +196,7 @@
     }
 
     @Fold
-    public static Kind wordKind() {
+    public static Kind getWordKind() {
         return graalRuntime().getTarget().wordKind;
     }
 
@@ -225,7 +220,7 @@
         return Unsafe.getUnsafe().pageSize();
     }
 
-    public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = LocationNode.createLocation("PrototypeMarkWord");
+    public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = new NamedLocationIdentity("PrototypeMarkWord");
 
     @Fold
     public static int prototypeMarkWordOffset() {
@@ -248,7 +243,7 @@
     }
 
     public static int readLayoutHelper(Word hub) {
-        return hub.readInt(klassLayoutHelperOffset(), FINAL_LOCATION);
+        return hub.readInt(klassLayoutHelperOffset(), LocationIdentity.FINAL_LOCATION);
     }
 
     @Fold
@@ -266,14 +261,14 @@
         return config().klassSuperKlassOffset;
     }
 
-    public static final LocationIdentity MARK_WORD_LOCATION = LocationNode.createLocation("MarkWord");
+    public static final LocationIdentity MARK_WORD_LOCATION = new NamedLocationIdentity("MarkWord");
 
     @Fold
     public static int markOffset() {
         return config().markOffset;
     }
 
-    public static final LocationIdentity HUB_LOCATION = LocationNode.createLocation("Hub");
+    public static final LocationIdentity HUB_LOCATION = new NamedLocationIdentity("Hub");
 
     @Fold
     private static int hubOffset() {
@@ -400,21 +395,21 @@
         return config().superCheckOffsetOffset;
     }
 
-    public static final LocationIdentity SECONDARY_SUPER_CACHE_LOCATION = LocationNode.createLocation("SecondarySuperCache");
+    public static final LocationIdentity SECONDARY_SUPER_CACHE_LOCATION = new NamedLocationIdentity("SecondarySuperCache");
 
     @Fold
     public static int secondarySuperCacheOffset() {
         return config().secondarySuperCacheOffset;
     }
 
-    public static final LocationIdentity SECONDARY_SUPERS_LOCATION = LocationNode.createLocation("SecondarySupers");
+    public static final LocationIdentity SECONDARY_SUPERS_LOCATION = new NamedLocationIdentity("SecondarySupers");
 
     @Fold
     public static int secondarySupersOffset() {
         return config().secondarySupersOffset;
     }
 
-    public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = LocationNode.createLocation("DisplacedMarkWord");
+    public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = new NamedLocationIdentity("DisplacedMarkWord");
 
     @Fold
     public static int lockDisplacedMarkOffset() {
@@ -445,16 +440,19 @@
      * Loads the hub from a object, null checking it first.
      */
     public static Word loadHub(Object object) {
-        return loadHubIntrinsic(object, wordKind());
+        return loadHubIntrinsic(object, getWordKind());
     }
 
     public static Object verifyOop(Object object) {
         if (verifyOops()) {
-            VerifyOopStubCall.call(object);
+            verifyOopStub(VERIFY_OOP, object);
         }
         return object;
     }
 
+    @NodeIntrinsic(ForeignCallNode.class)
+    private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
+
     /**
      * Gets the value of the stack pointer register as a Word.
      */
@@ -470,7 +468,7 @@
     }
 
     public static Word loadWordFromObject(Object object, int offset) {
-        return loadWordFromObjectIntrinsic(object, 0, offset, wordKind());
+        return loadWordFromObjectIntrinsic(object, 0, offset, getWordKind());
     }
 
     @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true)
@@ -493,7 +491,7 @@
         return CodeUtil.log2(wordSize());
     }
 
-    public static final LocationIdentity CLASS_STATE_LOCATION = LocationNode.createLocation("ClassState");
+    public static final LocationIdentity CLASS_STATE_LOCATION = new NamedLocationIdentity("ClassState");
 
     @Fold
     public static int klassStateOffset() {
@@ -525,14 +523,14 @@
         return config().klassInstanceSizeOffset;
     }
 
-    public static final LocationIdentity HEAP_TOP_LOCATION = LocationNode.createLocation("HeapTop");
+    public static final LocationIdentity HEAP_TOP_LOCATION = new NamedLocationIdentity("HeapTop");
 
     @Fold
     public static long heapTopAddress() {
         return config().heapTopAddress;
     }
 
-    public static final LocationIdentity HEAP_END_LOCATION = LocationNode.createLocation("HeapEnd");
+    public static final LocationIdentity HEAP_END_LOCATION = new NamedLocationIdentity("HeapEnd");
 
     @Fold
     public static long heapEndAddress() {
@@ -554,42 +552,42 @@
         return config().tlabAlignmentReserve;
     }
 
-    public static final LocationIdentity TLAB_SIZE_LOCATION = LocationNode.createLocation("TlabSize");
+    public static final LocationIdentity TLAB_SIZE_LOCATION = new NamedLocationIdentity("TlabSize");
 
     @Fold
     public static int threadTlabSizeOffset() {
         return config().threadTlabSizeOffset;
     }
 
-    public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = LocationNode.createLocation("TlabThreadAllocatedBytes");
+    public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = new NamedLocationIdentity("TlabThreadAllocatedBytes");
 
     @Fold
     public static int threadAllocatedBytesOffset() {
         return config().threadAllocatedBytesOffset;
     }
 
-    public static final LocationIdentity TLAB_REFILL_WASTE_LIMIT_LOCATION = LocationNode.createLocation("RefillWasteLimit");
+    public static final LocationIdentity TLAB_REFILL_WASTE_LIMIT_LOCATION = new NamedLocationIdentity("RefillWasteLimit");
 
     @Fold
     public static int tlabRefillWasteLimitOffset() {
         return config().tlabRefillWasteLimitOffset;
     }
 
-    public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = LocationNode.createLocation("TlabNOfRefills");
+    public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = new NamedLocationIdentity("TlabNOfRefills");
 
     @Fold
     public static int tlabNumberOfRefillsOffset() {
         return config().tlabNumberOfRefillsOffset;
     }
 
-    public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = LocationNode.createLocation("TlabFastRefillWaste");
+    public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = new NamedLocationIdentity("TlabFastRefillWaste");
 
     @Fold
     public static int tlabFastRefillWasteOffset() {
         return config().tlabFastRefillWasteOffset;
     }
 
-    public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = LocationNode.createLocation("TlabSlowAllocations");
+    public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = new NamedLocationIdentity("TlabSlowAllocations");
 
     @Fold
     public static int tlabSlowAllocationsOffset() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Thu May 23 14:44:01 2013 +0200
@@ -81,7 +81,7 @@
             return falseValue;
         }
         Word objectHub = loadHub(object);
-        if (probability(NOT_LIKELY_PROBABILITY, objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub))) {
+        if (probability(NOT_LIKELY_PROBABILITY, objectHub.readWord(superCheckOffset, LocationIdentity.FINAL_LOCATION).notEqual(hub))) {
             displayMiss.inc();
             return falseValue;
         }
@@ -171,7 +171,7 @@
                     args = new Arguments(instanceofSecondary);
                     args.add("hub", hub);
                     args.add("object", object);
-                    args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs);
+                    args.addVarargs("hints", Word.class, StampFactory.forKind(getWordKind()), hints.hubs);
                     args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive);
                 }
                 args.add("trueValue", replacer.trueValue);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Thu May 23 14:44:01 2013 +0200
@@ -35,12 +35,12 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
@@ -159,7 +159,7 @@
                         // owns the bias and we need to revoke that bias. The revocation will occur
                         // in the interpreter runtime.
                         traceObject(trace, "+lock{stub:revoke}", object);
-                        MonitorEnterStubCall.call(object, lock);
+                        monitorenterStub(MONITORENTER, object, lock);
                         return;
                     } else {
                         // At this point we know the epoch has expired, meaning that the
@@ -179,7 +179,7 @@
                         // succeeded in biasing it toward itself and we need to revoke that
                         // bias. The revocation will occur in the runtime in the slow case.
                         traceObject(trace, "+lock{stub:epoch-expired}", object);
-                        MonitorEnterStubCall.call(object, lock);
+                        monitorenterStub(MONITORENTER, object, lock);
                         return;
                     }
                 } else {
@@ -236,7 +236,7 @@
             if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) {
                 // Most likely not a recursive lock, go into a slow runtime call
                 traceObject(trace, "+lock{stub:failed-cas}", object);
-                MonitorEnterStubCall.call(object, lock);
+                monitorenterStub(MONITORENTER, object, lock);
                 return;
             } else {
                 // Recursively locked => write 0 to the lock slot
@@ -262,7 +262,7 @@
         // cannot float about the null check above
         final Word lock = beginLockScope(lockDepth);
         traceObject(trace, "+lock{stub}", object);
-        MonitorEnterStubCall.call(object, lock);
+        monitorenterStub(MONITORENTER, object, lock);
     }
 
     @Snippet
@@ -344,7 +344,7 @@
      */
     private static final boolean ENABLE_BREAKPOINT = false;
 
-    private static final LocationIdentity MONITOR_COUNTER_LOCATION = LocationNode.createLocation("MonitorCounter");
+    private static final LocationIdentity MONITOR_COUNTER_LOCATION = new NamedLocationIdentity("MonitorCounter");
 
     @NodeIntrinsic(BreakpointNode.class)
     static native void bkpt(Object object, Word mark, Word tmp, Word value);
@@ -517,4 +517,10 @@
             }
         }
     }
+
+    public static final ForeignCallDescriptor MONITORENTER = new ForeignCallDescriptor("monitorenter", void.class, Object.class, Word.class);
+
+    @NodeIntrinsic(ForeignCallNode.class)
+    private static native void monitorenterStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock);
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Thu May 23 14:44:01 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.api.code.UnsignedMath.*;
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Thu May 23 14:44:01 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java	Thu May 23 14:44:01 2013 +0200
@@ -25,8 +25,8 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -40,7 +40,7 @@
     @MethodSubstitution(isStatic = false)
     public static Class<?> getClass(final Object thisObj) {
         Word hub = loadHub(thisObj);
-        return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationNode.FINAL_LOCATION), Class.class, true, true);
+        return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
     }
 
     @MethodSubstitution(isStatic = false)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Thu May 23 14:44:01 2013 +0200
@@ -22,10 +22,18 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -36,21 +44,37 @@
 
     @MethodSubstitution
     public static Thread currentThread() {
-        return (Thread) CurrentJavaThreadNode.get().readObject(threadObjectOffset(), FINAL_LOCATION);
+        return (Thread) CurrentJavaThreadNode.get().readObject(threadObjectOffset(), LocationIdentity.FINAL_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
     public static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) {
         Word javaThread = CurrentJavaThreadNode.get();
-        Object thread = javaThread.readObject(threadObjectOffset(), FINAL_LOCATION);
+        Object thread = javaThread.readObject(threadObjectOffset(), LocationIdentity.FINAL_LOCATION);
         if (thisObject == thread) {
-            Word osThread = javaThread.readWord(osThreadOffset(), FINAL_LOCATION);
+            Word osThread = javaThread.readWord(osThreadOffset(), LocationIdentity.FINAL_LOCATION);
             boolean interrupted = osThread.readInt(osThreadInterruptedOffset(), ANY_LOCATION) != 0;
             if (!interrupted || !clearInterrupted) {
                 return interrupted;
             }
         }
 
-        return ThreadIsInterruptedStubCall.call(thisObject, clearInterrupted);
+        return threadIsInterruptedStub(THREAD_IS_INTERRUPTED, thisObject, clearInterrupted);
+    }
+
+    public static final ForeignCallDescriptor THREAD_IS_INTERRUPTED = new ForeignCallDescriptor("thread_is_interrupted", boolean.class, Object.class, boolean.class);
+
+    /**
+     * @param descriptor
+     */
+    @NodeIntrinsic(ForeignCallNode.class)
+    private static boolean threadIsInterruptedStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Thread thread, boolean clearIsInterrupted) {
+        try {
+            Method isInterrupted = Thread.class.getDeclaredMethod("isInterrupted", boolean.class);
+            isInterrupted.setAccessible(true);
+            return (Boolean) isInterrupted.invoke(thread, clearIsInterrupted);
+        } catch (Exception e) {
+            throw new GraalInternalError(e);
+        }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Thu May 23 14:44:01 2013 +0200
@@ -32,8 +32,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
@@ -45,7 +43,7 @@
  */
 public class TypeCheckSnippetUtils {
 
-    public static final LocationIdentity TYPE_DISPLAY_LOCATION = LocationNode.createLocation("TypeDisplay");
+    public static final LocationIdentity TYPE_DISPLAY_LOCATION = new NamedLocationIdentity("TypeDisplay");
 
     static boolean checkSecondarySubType(Word t, Word s) {
         // if (S.cache == T) return true
@@ -59,7 +57,7 @@
 
     static boolean checkUnknownSubType(Word t, Word s) {
         // int off = T.offset
-        int superCheckOffset = t.readInt(superCheckOffsetOffset(), FINAL_LOCATION);
+        int superCheckOffset = t.readInt(superCheckOffsetOffset(), LocationIdentity.FINAL_LOCATION);
         boolean primary = superCheckOffset != secondarySuperCacheOffset();
 
         // if (T = S[off]) return true
@@ -90,7 +88,7 @@
 
         // if (S.scan_s_s_array(T)) { S.cache = T; return true; }
         Word secondarySupers = s.readWord(secondarySupersOffset(), SECONDARY_SUPERS_LOCATION);
-        int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), FINAL_LOCATION);
+        int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), LocationIdentity.FINAL_LOCATION);
         for (int i = 0; i < length; i++) {
             if (probability(NOT_LIKELY_PROBABILITY, t.equal(loadSecondarySupersElement(secondarySupers, i)))) {
                 s.writeWord(secondarySuperCacheOffset(), t, SECONDARY_SUPER_CACHE_LOCATION);
@@ -144,7 +142,7 @@
     }
 
     static Word loadSecondarySupersElement(Word metaspaceArray, int index) {
-        return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), FINAL_LOCATION);
+        return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), LocationIdentity.FINAL_LOCATION);
     }
 
     private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("TypeCheck") : null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Thu May 23 14:44:01 2013 +0200
@@ -80,13 +80,18 @@
      * @param descriptor the signature of the call to this stub
      * @param prependThread true if the JavaThread value for the current thread is to be prepended
      *            to the arguments for the call to {@code address}
+     * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side
+     *            effects. Deoptimization will not return to a point before a stub call that cannot
+     *            be re-executed.
+     * @param killedLocations the memory locations killed by the stub call
      */
-    public ForeignCallStub(long address, ForeignCallDescriptor descriptor, boolean prependThread, HotSpotRuntime runtime, Replacements replacements) {
-        super(runtime, replacements, HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF));
+    public ForeignCallStub(HotSpotRuntime runtime, Replacements replacements, long address, ForeignCallDescriptor descriptor, boolean prependThread, boolean reexecutable,
+                    LocationIdentity... killedLocations) {
+        super(runtime, replacements, HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF, reexecutable, killedLocations));
         this.prependThread = prependThread;
         Class[] targetParameterTypes = createTargetParameters(descriptor);
         ForeignCallDescriptor targetSig = new ForeignCallDescriptor(descriptor.getName() + ":C", descriptor.getResultType(), targetParameterTypes);
-        target = HotSpotForeignCallLinkage.create(targetSig, address, DESTROYS_REGISTERS, NativeCall, NOT_LEAF);
+        target = HotSpotForeignCallLinkage.create(targetSig, address, DESTROYS_REGISTERS, NativeCall, NOT_LEAF, reexecutable, killedLocations);
     }
 
     /**
@@ -283,9 +288,9 @@
             ValueNode[] targetArguments = new ValueNode[1 + locals.length];
             targetArguments[0] = thread;
             System.arraycopy(locals, 0, targetArguments, 1, locals.length);
-            return builder.append(new ForeignCallNode(target.getDescriptor(), targetArguments));
+            return builder.append(new ForeignCallNode(runtime, target.getDescriptor(), targetArguments));
         } else {
-            return builder.append(new ForeignCallNode(target.getDescriptor(), locals));
+            return builder.append(new ForeignCallNode(runtime, target.getDescriptor(), locals));
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Thu May 23 14:44:01 2013 +0200
@@ -89,7 +89,7 @@
      */
     @Snippet
     private static Object newArray(Word hub, int length, @ConstantParameter Word intArrayHub) {
-        int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
+        int layoutHelper = hub.readInt(layoutHelperOffset(), LocationIdentity.FINAL_LOCATION);
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
         int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Thu May 23 14:44:01 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
@@ -87,7 +88,7 @@
      */
     @Snippet
     private static Object newInstance(Word hub, @ConstantParameter Word intArrayHub) {
-        int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION);
+        int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), LocationIdentity.FINAL_LOCATION);
         if (!forceSlowPath() && inlineContiguousAllocationSupported()) {
             if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) {
                 Word memory = refillAllocate(intArrayHub, sizeInBytes, logging());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java	Thu May 23 14:44:01 2013 +0200
@@ -27,12 +27,11 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 
 /**
- * Stub called from {@link VerifyOopStubCall}.
+ * Stub called via {@link HotSpotRuntime#VERIFY_OOP}.
  */
 public class VerifyOopStub extends SnippetStub {
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu May 23 14:44:01 2013 +0200
@@ -925,7 +925,7 @@
             ValueNode exception = ConstantNode.forObject(cachedNullPointerException, runtime, currentGraph);
             trueSucc.setNext(handleException(exception, bci()));
         } else {
-            ForeignCallStateSplitNode call = currentGraph.add(new ForeignCallStateSplitNode(runtime, CREATE_NULL_POINTER_EXCEPTION));
+            ForeignCallNode call = currentGraph.add(new ForeignCallNode(runtime, CREATE_NULL_POINTER_EXCEPTION));
             call.setStateAfter(frameState.create(bci()));
             trueSucc.setNext(call);
             call.setNext(handleException(call, bci()));
@@ -949,7 +949,7 @@
             ValueNode exception = ConstantNode.forObject(cachedArrayIndexOutOfBoundsException, runtime, currentGraph);
             falseSucc.setNext(handleException(exception, bci()));
         } else {
-            ForeignCallStateSplitNode call = currentGraph.add(new ForeignCallStateSplitNode(runtime, CREATE_OUT_OF_BOUNDS_EXCEPTION, index));
+            ForeignCallNode call = currentGraph.add(new ForeignCallNode(runtime, CREATE_OUT_OF_BOUNDS_EXCEPTION, index));
             call.setStateAfter(frameState.create(bci()));
             falseSucc.setNext(call);
             call.setNext(handleException(call, bci()));
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Thu May 23 14:44:01 2013 +0200
@@ -273,7 +273,7 @@
         protected void verify() {
             super.verify();
             // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx
-            assert asRegister(x) == AMD64.rax;
+            assert asRegister(x).equals(AMD64.rax);
             assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue());
             verifyKind(opcode, divResult, x, y);
             verifyKind(opcode, remResult, x, y);
@@ -360,9 +360,9 @@
                 case IMUL: masm.imull(asIntReg(dst), asIntReg(src)); break;
                 case IOR:  masm.orl(asIntReg(dst),   asIntReg(src)); break;
                 case IXOR: masm.xorl(asIntReg(dst),  asIntReg(src)); break;
-                case ISHL: assert asIntReg(src) == AMD64.rcx; masm.shll(asIntReg(dst)); break;
-                case ISHR: assert asIntReg(src) == AMD64.rcx; masm.sarl(asIntReg(dst)); break;
-                case IUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrl(asIntReg(dst)); break;
+                case ISHL: assert asIntReg(src).equals(AMD64.rcx); masm.shll(asIntReg(dst)); break;
+                case ISHR: assert asIntReg(src).equals(AMD64.rcx); masm.sarl(asIntReg(dst)); break;
+                case IUSHR: assert asIntReg(src).equals(AMD64.rcx); masm.shrl(asIntReg(dst)); break;
 
                 case LADD: masm.addq(asLongReg(dst),  asLongReg(src)); break;
                 case LSUB: masm.subq(asLongReg(dst),  asLongReg(src)); break;
@@ -370,9 +370,9 @@
                 case LAND: masm.andq(asLongReg(dst),  asLongReg(src)); break;
                 case LOR:  masm.orq(asLongReg(dst),   asLongReg(src)); break;
                 case LXOR: masm.xorq(asLongReg(dst),  asLongReg(src)); break;
-                case LSHL: assert asIntReg(src) == AMD64.rcx; masm.shlq(asLongReg(dst)); break;
-                case LSHR: assert asIntReg(src) == AMD64.rcx; masm.sarq(asLongReg(dst)); break;
-                case LUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrq(asLongReg(dst)); break;
+                case LSHL: assert asIntReg(src).equals(AMD64.rcx); masm.shlq(asLongReg(dst)); break;
+                case LSHR: assert asIntReg(src).equals(AMD64.rcx); masm.sarq(asLongReg(dst)); break;
+                case LUSHR: assert asIntReg(src).equals(AMD64.rcx); masm.shrq(asLongReg(dst)); break;
 
                 case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); break;
                 case FSUB: masm.subss(asFloatReg(dst), asFloatReg(src)); break;
@@ -556,6 +556,6 @@
             || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
             || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float)
             || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double)
-            || (opcode.name().matches(".U?SH.") && result.getKind() == x.getKind() && y.getKind() == Kind.Int && (isConstant(y) || asRegister(y) == AMD64.rcx));
+            || (opcode.name().matches(".U?SH.") && result.getKind() == x.getKind() && y.getKind() == Kind.Int && (isConstant(y) || asRegister(y).equals(AMD64.rcx)));
     }
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Thu May 23 14:44:01 2013 +0200
@@ -404,7 +404,7 @@
 
     private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, ConditionFlag cond, Value other) {
         if (isRegister(other)) {
-            assert asRegister(other) != asRegister(result) : "other already overwritten by previous move";
+            assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move";
             switch (other.getKind()) {
                 case Int:  masm.cmovl(cond, asRegister(result), asRegister(other)); break;
                 case Long: masm.cmovq(cond, asRegister(result), asRegister(other)); break;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Thu May 23 14:44:01 2013 +0200
@@ -526,7 +526,7 @@
     }
 
     protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
-        assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax;
+        assert asRegister(cmpValue).equals(AMD64.rax) && asRegister(result).equals(AMD64.rax);
 
         if (tasm.target.isMP) {
             masm.lock();
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Thu May 23 14:44:01 2013 +0200
@@ -31,7 +31,9 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.LIRInstruction.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.nodes.cfg.*;
 
 public final class LIRVerifier {
@@ -230,14 +232,17 @@
         return value;
     }
 
+    // @formatter:off
     private static Value allowed(Object op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        if ((isVariable(value) && flags.contains(OperandFlag.REG)) || (isRegister(value) && flags.contains(OperandFlag.REG)) || (isStackSlot(value) && flags.contains(OperandFlag.STACK)) ||
-                        (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) {
+        if ((isVariable(value) && flags.contains(OperandFlag.REG)) ||
+            (isRegister(value) && flags.contains(OperandFlag.REG)) ||
+            (isStackSlot(value) && flags.contains(OperandFlag.STACK)) ||
+            (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) ||
+            (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) {
             return value;
         }
-        TTY.println("instruction %s", op);
-        TTY.println("mode: %s  flags: %s", mode, flags);
-        TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value);
-        throw GraalInternalError.shouldNotReachHere();
+        throw new GraalInternalError("Invalid LIR%n  Instruction: %s%n  Mode: %s%n  Flags: %s%n  Unexpected value: %s %s",
+                        op, mode, flags, value.getClass().getSimpleName(), value);
     }
+    // @formatter:on
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Thu May 23 14:44:01 2013 +0200
@@ -83,9 +83,4 @@
     public DeoptimizationReason getDeoptimizationReason() {
         return reason;
     }
-
-    @Override
-    public boolean isCallSiteDeoptimization() {
-        return false;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Thu May 23 14:44:01 2013 +0200
@@ -42,9 +42,4 @@
         updateUsages(deoptState, f);
         deoptState = f;
     }
-
-    @Override
-    public boolean isCallSiteDeoptimization() {
-        return false;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Thu May 23 14:44:01 2013 +0200
@@ -25,29 +25,24 @@
 import com.oracle.graal.api.meta.*;
 
 /**
- * Interface that needs to be implemented by nodes which need deoptimization information.
- * 
+ * Interface implemented by nodes which need deoptimization information.
  */
 public interface DeoptimizingNode {
 
     /**
-     * Returns true if this particular instance needs deoptimization information.
-     * 
-     * @return true if this particular instance needs deoptimization information
+     * Determines if this node needs deoptimization information.
      */
     boolean canDeoptimize();
 
     /**
-     * Returns the deoptimization information associated with this node if any.
-     * 
-     * @return the deoptimization information associated with this node if any.
+     * Gets the deoptimization information associated with this node if any.
      */
     FrameState getDeoptimizationState();
 
     /**
-     * Set the deoptimization information associated with this node.
+     * Sets the deoptimization information associated with this node.
      * 
-     * @param state the FrameState which represents the deoptimization information.
+     * @param state the FrameState which represents the deoptimization information
      */
     void setDeoptimizationState(FrameState state);
 
@@ -59,13 +54,4 @@
      * @return the reason for deoptimization triggered by this node.
      */
     DeoptimizationReason getDeoptimizationReason();
-
-    /**
-     * Returns true if this node needs deoptimization information for stack-walking purposes because
-     * it is a call-site. While most other nodes use deoptimization information representing a state
-     * that happened before them, these nodes use a state that is valid during the call itself.
-     * 
-     * @return true if this node needs deoptimization information for stack-walking purposes.
-     */
-    boolean isCallSiteDeoptimization();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,13 +22,15 @@
  */
 package com.oracle.graal.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.Stamp;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -47,11 +49,22 @@
     /**
      * Constructs a new Invoke instruction.
      * 
+     * @param callTarget the target method being called
      * @param bci the bytecode index of the original invoke (used for debug infos)
-     * @param callTarget the target method being called
      */
     public InvokeNode(CallTargetNode callTarget, int bci) {
-        super(callTarget.returnStamp());
+        this(callTarget, bci, callTarget.returnStamp());
+    }
+
+    /**
+     * Constructs a new Invoke instruction.
+     * 
+     * @param callTarget the target method being called
+     * @param bci the bytecode index of the original invoke (used for debug infos)
+     * @param stamp the stamp to be used for this value
+     */
+    public InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp) {
+        super(stamp);
         this.callTarget = callTarget;
         this.bci = bci;
         this.polymorphic = false;
@@ -93,7 +106,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
@@ -188,11 +201,6 @@
     }
 
     @Override
-    public boolean isCallSiteDeoptimization() {
-        return true;
-    }
-
-    @Override
     public GuardingNode getGuard() {
         return guard;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
@@ -154,7 +155,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     public FrameState stateDuring() {
@@ -237,11 +238,6 @@
     }
 
     @Override
-    public boolean isCallSiteDeoptimization() {
-        return true;
-    }
-
-    @Override
     public GuardingNode getGuard() {
         return guard;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Thu May 23 14:44:01 2013 +0200
@@ -61,12 +61,6 @@
 
     @Override
     public boolean inferStamp() {
-        if (stamp() instanceof ObjectStamp && object().objectStamp().alwaysNull() && objectStamp().nonNull()) {
-            // a null value flowing into a nonNull PiNode should be guarded by a type/isNull guard,
-            // but the
-            // compiler might see this situation before the branch is deleted
-            return false;
-        }
         return updateStamp(stamp().join(object().stamp()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,8 +22,10 @@
  */
 package com.oracle.graal.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 
 /**
  * The start node of a graph.
@@ -32,6 +34,6 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu May 23 14:44:01 2013 +0200
@@ -60,7 +60,7 @@
      * @return true if the stamp has changed, false otherwise.
      */
     protected final boolean updateStamp(Stamp newStamp) {
-        if (newStamp.equals(stamp)) {
+        if (newStamp == null || newStamp.equals(stamp)) {
             return false;
         } else {
             stamp = newStamp;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Thu May 23 14:44:01 2013 +0200
@@ -91,10 +91,5 @@
         deoptState = f;
     }
 
-    @Override
-    public boolean isCallSiteDeoptimization() {
-        return false;
-    }
-
     public abstract Access asFixedNode();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Thu May 23 14:44:01 2013 +0200
@@ -26,7 +26,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -34,22 +33,31 @@
  * Node for a {@linkplain ForeignCallDescriptor foreign} call.
  */
 @NodeInfo(nameTemplate = "ForeignCall#{p#descriptor/s}")
-public class ForeignCallNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint {
+public class ForeignCallNode extends AbstractStateSplit implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint {
 
     @Input private final NodeInputList<ValueNode> arguments;
+    private final MetaAccessProvider runtime;
+    @Input private FrameState deoptState;
 
     private final ForeignCallDescriptor descriptor;
 
-    public ForeignCallNode(ForeignCallDescriptor descriptor, ValueNode... arguments) {
+    public ForeignCallNode(MetaAccessProvider runtime, ForeignCallDescriptor descriptor, ValueNode... arguments) {
         super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())));
         this.arguments = new NodeInputList<>(this, arguments);
         this.descriptor = descriptor;
+        this.runtime = runtime;
     }
 
-    protected ForeignCallNode(ForeignCallDescriptor descriptor, Stamp stamp) {
+    protected ForeignCallNode(MetaAccessProvider runtime, ForeignCallDescriptor descriptor, Stamp stamp) {
         super(stamp);
         this.arguments = new NodeInputList<>(this);
         this.descriptor = descriptor;
+        this.runtime = runtime;
+    }
+
+    @Override
+    public boolean hasSideEffect() {
+        return !runtime.isReexecutable(descriptor);
     }
 
     public ForeignCallDescriptor getDescriptor() {
@@ -58,7 +66,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return runtime.getKilledLocationIdentities(descriptor);
     }
 
     protected Value[] operands(LIRGeneratorTool gen) {
@@ -80,6 +88,30 @@
     }
 
     @Override
+    public FrameState getDeoptimizationState() {
+        if (deoptState != null) {
+            return deoptState;
+        } else if (stateAfter() != null) {
+            FrameState stateDuring = stateAfter();
+            if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) {
+                stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.kind());
+            }
+            setDeoptimizationState(stateDuring);
+            return stateDuring;
+        }
+        return null;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        updateUsages(deoptState, f);
+        if (deoptState != null) {
+            throw new IllegalStateException(toString(Verbosity.Debugger));
+        }
+        deoptState = f;
+    }
+
+    @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Name) {
             return super.toString(verbosity) + "#" + descriptor;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallStateSplitNode.java	Fri May 17 16:47:13 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +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.graal.nodes.extended;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * A foreign call that is also a state split.
- */
-@NodeInfo(nameTemplate = "ForeignCallStateSplit#{p#descriptor/s}")
-public class ForeignCallStateSplitNode extends ForeignCallNode implements LIRLowerable, StateSplit, DeoptimizingNode {
-
-    @Input(notDataflow = true) private FrameState stateAfter;
-    private MetaAccessProvider runtime;
-
-    public ForeignCallStateSplitNode(MetaAccessProvider runtime, ForeignCallDescriptor descriptor, ValueNode... arguments) {
-        super(descriptor, arguments);
-        this.runtime = runtime;
-    }
-
-    public FrameState stateAfter() {
-        return stateAfter;
-    }
-
-    public void setStateAfter(FrameState x) {
-        assert x == null || x.isAlive() : "frame state must be in a graph";
-        updateUsages(stateAfter, x);
-        stateAfter = x;
-    }
-
-    public boolean hasSideEffect() {
-        return runtime.hasSideEffect(getDescriptor());
-    }
-
-    @Override
-    public FrameState getDeoptimizationState() {
-        if (super.getDeoptimizationState() != null) {
-            return super.getDeoptimizationState();
-        } else if (stateAfter() != null) {
-            FrameState stateDuring = stateAfter();
-            if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) {
-                stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.kind());
-            }
-            setDeoptimizationState(stateDuring);
-            return stateDuring;
-        }
-        return null;
-    }
-
-    @Override
-    public void setDeoptimizationState(FrameState f) {
-        if (super.getDeoptimizationState() != null) {
-            throw new IllegalStateException();
-        }
-        super.setDeoptimizationState(f);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import java.util.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.nodes.calc.*;
@@ -38,61 +36,6 @@
 public abstract class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable {
 
     /**
-     * Marker interface for location identities. Apart from the special values {@link #ANY_LOCATION}
-     * and {@link #FINAL_LOCATION}, a different location identity of two memory accesses guarantees
-     * that the two accesses do not interfere.
-     */
-    public interface LocationIdentity {
-    }
-
-    /**
-     * Denotes any location. A write to such a location kills all values in a memory map during an
-     * analysis of memory accesses in a graph. A read from this location cannot be moved or
-     * coalesced with other reads because its interaction with other reads is not known.
-     */
-    public static final LocationIdentity ANY_LOCATION = createLocation("ANY_LOCATION");
-
-    /**
-     * Denotes the location of a value that is guaranteed to be final.
-     */
-    public static final LocationIdentity FINAL_LOCATION = createLocation("FINAL_LOCATION");
-
-    /**
-     * Creates a new unique location identity for read and write operations.
-     * 
-     * @param name the name of the new location identity, for debugging purposes
-     * @return the new location identity
-     */
-    public static LocationIdentity createLocation(final String name) {
-        return new LocationIdentity() {
-
-            @Override
-            public String toString() {
-                return name;
-            }
-        };
-    }
-
-    /**
-     * Returns the location identity for an array of the given element kind. Array accesses of the
-     * same kind must have the same location identity unless an alias analysis guarantees that two
-     * distinct arrays are accessed.
-     */
-    public static LocationIdentity getArrayLocation(Kind elementKind) {
-        return ARRAY_LOCATIONS.get(elementKind);
-    }
-
-    private static final EnumMap<Kind, LocationIdentity> ARRAY_LOCATIONS = initArrayLocations();
-
-    private static EnumMap<Kind, LocationIdentity> initArrayLocations() {
-        EnumMap<Kind, LocationIdentity> result = new EnumMap<>(Kind.class);
-        for (Kind kind : Kind.values()) {
-            result.put(kind, createLocation("Array: " + kind.getJavaName()));
-        }
-        return result;
-    }
-
-    /**
      * Marker interface for locations in snippets.
      */
     public interface Location {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import java.lang.reflect.*;
@@ -29,9 +30,9 @@
 import sun.misc.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -52,7 +53,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Thu May 23 14:44:01 2013 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 
 /**
  * This interface marks subclasses of {@link FixedNode} that kill a set of memory locations
@@ -34,7 +34,7 @@
 
     /**
      * 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.
+     * Returning the special value {@link LocationIdentity#ANY_LOCATION} will kill all memory locations.
      * 
      * @return the identities of all locations killed by this node.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu May 23 14:44:01 2013 +0200
@@ -25,7 +25,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -77,7 +76,7 @@
             return null;
         }
         if (runtime != null && object != null && object.isConstant()) {
-            if (location.getLocationIdentity() == LocationNode.FINAL_LOCATION && location instanceof ConstantLocationNode) {
+            if (location.getLocationIdentity() == LocationIdentity.FINAL_LOCATION && location instanceof ConstantLocationNode) {
                 long displacement = ((ConstantLocationNode) location).getDisplacement();
                 Kind kind = location.getValueKind();
                 if (object.kind() == Kind.Object) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -74,7 +76,7 @@
             return (LocationIdentity) locationIdentity.asConstant().asObject();
         }
         // We do not know our actual location identity yet, so be conservative.
-        return LocationNode.ANY_LOCATION;
+        return ANY_LOCATION;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Thu May 23 14:44:01 2013 +0200
@@ -52,12 +52,6 @@
         if (stamp() == StampFactory.forNodeIntrinsic()) {
             return false;
         }
-        if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) {
-            // a null value flowing into a nonNull UnsafeCastNode should be guarded by a type/isNull
-            // guard, but the
-            // compiler might see this situation before the branch is deleted
-            return false;
-        }
         return updateStamp(stamp().join(object().stamp()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -76,7 +76,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,8 +22,10 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -39,7 +41,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Thu May 23 14:44:01 2013 +0200
@@ -26,7 +26,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.LocationNode.Location;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Thu May 23 14:44:01 2013 +0200
@@ -69,9 +69,6 @@
 
     @Override
     public boolean inferStamp() {
-        if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) {
-            return false;
-        }
         return updateStamp(stamp().join(object().stamp()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,13 +22,13 @@
  */
 package com.oracle.graal.nodes.java;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -97,7 +97,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.nodes.java;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -41,7 +42,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,9 +22,11 @@
  */
 package com.oracle.graal.nodes.java;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -46,7 +48,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,10 +22,12 @@
  */
 package com.oracle.graal.nodes.java;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -47,7 +49,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Thu May 23 14:44:01 2013 +0200
@@ -106,11 +106,6 @@
         return null;
     }
 
-    @Override
-    public boolean isCallSiteDeoptimization() {
-        return false;
-    }
-
     @SuppressWarnings("unused")
     @NodeIntrinsic
     public static void register(Object thisObj) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Thu May 23 14:44:01 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.type;
 
+import java.lang.reflect.*;
+
 import com.oracle.graal.api.meta.*;
 
 public class ObjectStamp extends Stamp {
@@ -33,14 +35,29 @@
 
     public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
         super(Kind.Object);
-        assert !exactType || type != null;
-        assert !(nonNull && alwaysNull);
+        assert isValid(type, exactType, nonNull, alwaysNull);
         this.type = type;
         this.exactType = exactType;
         this.nonNull = nonNull;
         this.alwaysNull = alwaysNull;
     }
 
+    public static boolean isValid(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
+        if (exactType && type == null) {
+            return false;
+        }
+
+        if (exactType && Modifier.isAbstract(type.getModifiers()) && !type.isArray()) {
+            return false;
+        }
+
+        if (nonNull && alwaysNull) {
+            return false;
+        }
+
+        return true;
+    }
+
     @Override
     public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
         if (type != null) {
@@ -152,12 +169,19 @@
                 joinType = type;
             }
         }
+
         if (joinType == type && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) {
             return this;
         } else if (joinType == other.type && joinExactType == other.exactType && joinNonNull == other.nonNull && joinAlwaysNull == other.alwaysNull) {
             return other;
         } else {
-            return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull);
+            if (isValid(joinType, joinExactType, joinNonNull, joinAlwaysNull)) {
+                return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull);
+            } else {
+                // This situation can happen in case the compiler wants to join two contradicting
+                // stamps.
+                return null;
+            }
         }
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Thu May 23 14:44:01 2013 +0200
@@ -22,12 +22,14 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.graph.ReentrantNodeIterator.LoopInfo;
@@ -45,7 +47,7 @@
 
         public MemoryMap(StartNode start) {
             this();
-            lastMemorySnapshot.put(LocationNode.ANY_LOCATION, start);
+            lastMemorySnapshot.put(ANY_LOCATION, start);
         }
 
         public MemoryMap() {
@@ -54,12 +56,12 @@
 
         private ValueNode getLastLocationAccess(LocationIdentity locationIdentity) {
             ValueNode lastLocationAccess;
-            if (locationIdentity == LocationNode.FINAL_LOCATION) {
+            if (locationIdentity == FINAL_LOCATION) {
                 return null;
             } else {
                 lastLocationAccess = lastMemorySnapshot.get(locationIdentity);
                 if (lastLocationAccess == null) {
-                    lastLocationAccess = lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
+                    lastLocationAccess = lastMemorySnapshot.get(ANY_LOCATION);
                     assert lastLocationAccess != null;
                 }
                 return lastLocationAccess;
@@ -122,7 +124,7 @@
                 exit.addAll(modifiedLocations);
                 exit.addAll(initialState);
             }
-            assert !modifiedLocations.contains(LocationNode.FINAL_LOCATION);
+            assert !modifiedLocations.contains(FINAL_LOCATION);
             modifiedInLoops.put(loop, modifiedLocations);
             return loopInfo.exitStates;
         }
@@ -149,7 +151,7 @@
 
         private static void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) {
             for (LocationIdentity identity : checkpoint.getLocationIdentities()) {
-                if (identity == LocationNode.ANY_LOCATION) {
+                if (identity == ANY_LOCATION) {
                     state.lastMemorySnapshot.clear();
                 }
                 state.lastMemorySnapshot.put(identity, (ValueNode) checkpoint);
@@ -160,7 +162,7 @@
             StructuredGraph graph = accessNode.graph();
             assert accessNode.getNullCheck() == false;
             LocationIdentity locationIdentity = accessNode.location().getLocationIdentity();
-            if (locationIdentity != LocationNode.ANY_LOCATION) {
+            if (locationIdentity != ANY_LOCATION) {
                 ValueNode lastLocationAccess = state.getLastLocationAccess(locationIdentity);
                 FloatingAccessNode floatingNode = accessNode.asFloatingNode(lastLocationAccess);
                 floatingNode.setNullCheck(accessNode.getNullCheck());
@@ -182,7 +184,7 @@
             for (MemoryMap other : states) {
                 keys.addAll(other.lastMemorySnapshot.keySet());
             }
-            assert !keys.contains(LocationNode.FINAL_LOCATION);
+            assert !keys.contains(FINAL_LOCATION);
 
             for (LocationIdentity key : keys) {
                 int mergedStatesCount = 0;
@@ -236,7 +238,7 @@
         @Override
         protected Map<LoopExitNode, MemoryMap> processLoop(LoopBeginNode loop, MemoryMap initialState) {
             Set<LocationIdentity> modifiedLocations = modifiedInLoops.get(loop);
-            if (modifiedLocations.contains(LocationNode.ANY_LOCATION)) {
+            if (modifiedLocations.contains(ANY_LOCATION)) {
                 // create phis for all locations if ANY is modified in the loop
                 modifiedLocations = new HashSet<>(modifiedLocations);
                 modifiedLocations.addAll(initialState.lastMemorySnapshot.keySet());
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Thu May 23 14:44:01 2013 +0200
@@ -255,7 +255,7 @@
                         callerHasMoreInformationAboutArguments = true;
                     } else {
                         Stamp joinedStamp = localNode.stamp().join(arg.stamp());
-                        if (!joinedStamp.equals(localNode.stamp())) {
+                        if (joinedStamp != null && !joinedStamp.equals(localNode.stamp())) {
                             localNode.setStamp(joinedStamp);
                             callerHasMoreInformationAboutArguments = true;
                         }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Thu May 23 14:44:01 2013 +0200
@@ -60,7 +60,7 @@
     public static int     TrivialInliningSize                = 10;
     public static int     MaximumInliningSize                = 300;
     public static int     SmallCompiledLowLevelGraphSize     = 300;
-    public static double  LimitInlinedInvokes                = 10.0;
+    public static double  LimitInlinedInvokes                = 5.0;
 
     // escape analysis settings
     public static boolean PartialEscapeAnalysis              = true;
@@ -152,6 +152,7 @@
     public static int     TraceBytecodeParserLevel           = 0;
     public static boolean ExitVMOnBailout                    = ____;
     public static boolean ExitVMOnException                  = true;
+    public static boolean PrintStackTraceOnException         = false;
 
     // HotSpot command line options
     public static boolean HotSpotPrintCompilation            = ____;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/VerifyPhase.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/VerifyPhase.java	Thu May 23 14:44:01 2013 +0200
@@ -24,6 +24,12 @@
 
 import com.oracle.graal.nodes.*;
 
+/***
+ * This phase serves as a verification, in order to check the graph for certain properties. The
+ * {@link #verify(StructuredGraph)} method will be used as an assertion, and implements the actual
+ * check. Instead of returning false, it is also valid to throw an {@link AssertionError} in the
+ * implemented {@link #verify(StructuredGraph)} method.
+ */
 public abstract class VerifyPhase extends Phase {
 
     @Override
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Thu May 23 14:44:01 2013 +0200
@@ -22,8 +22,11 @@
  */
 package com.oracle.graal.phases.schedule;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
@@ -31,7 +34,6 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
@@ -98,7 +100,7 @@
                         for (Iterator<FloatingReadNode> iter = currentState.iterator(); iter.hasNext();) {
                             FloatingReadNode read = iter.next();
                             FixedNode fixed = (FixedNode) node;
-                            if (identity == LocationNode.ANY_LOCATION || read.location().getLocationIdentity() == identity) {
+                            if (identity == ANY_LOCATION || read.location().getLocationIdentity() == identity) {
                                 addPhantomReference(read, fixed);
                                 iter.remove();
                             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Thu May 23 14:44:01 2013 +0200
@@ -0,0 +1,82 @@
+/*
+ * 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.phases.verify;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * For certain types object identity should not be used for object equality check. This phase checks
+ * the correct usage of the given type. Equality checks with == or != (except null checks) results
+ * in an {@link AssertionError}.
+ */
+public class VerifyUsageWithEquals extends VerifyPhase {
+
+    private MetaAccessProvider runtime;
+    private Class<?> klass;
+
+    public VerifyUsageWithEquals(MetaAccessProvider runtime, Class<?> klass) {
+        this.runtime = runtime;
+        this.klass = klass;
+    }
+
+    private boolean isAssignableType(ValueNode node) {
+        if (node.stamp() instanceof ObjectStamp) {
+            ResolvedJavaType valueType = runtime.lookupJavaType(klass);
+            ResolvedJavaType nodeType = node.objectStamp().type();
+
+            if (nodeType != null && valueType.isAssignableFrom(nodeType)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean isNullConstant(ValueNode node) {
+        return node.isConstant() && node.asConstant().isNull();
+    }
+
+    private boolean checkUsage(ValueNode x, ValueNode y) {
+        return isAssignableType(x) && !isNullConstant(y);
+    }
+
+    private static boolean isEqualsMethod(StructuredGraph graph) {
+        Signature signature = graph.method().getSignature();
+        return graph.method().getName().equals("equals") && signature.getParameterCount(false) == 1 && signature.getParameterKind(0).equals(Kind.Object);
+    }
+
+    @Override
+    protected boolean verify(StructuredGraph graph) {
+        for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) {
+            if (!isEqualsMethod(graph)) {
+                // bail out if we compare an object of type klass with == or != (except null checks)
+                assert !(checkUsage(cn.x(), cn.y()) && checkUsage(cn.y(), cn.x())) : "Verifcation of " + klass.getName() + " usage failed: Comparison " + cn.x() + " and" + cn.y() + " in " +
+                                graph.method() + " must use .equals() for object equality, not '==' or '!='";
+            }
+        }
+        return true;
+    }
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyValueUsage.java	Fri May 17 16:47:13 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.verify;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.phases.*;
-
-public class VerifyValueUsage extends VerifyPhase {
-
-    private MetaAccessProvider runtime;
-
-    public VerifyValueUsage(MetaAccessProvider runtime) {
-        this.runtime = runtime;
-    }
-
-    private boolean checkType(ValueNode node) {
-        if (node.stamp() instanceof ObjectStamp) {
-            ResolvedJavaType valueType = runtime.lookupJavaType(Value.class);
-            ResolvedJavaType nodeType = node.objectStamp().type();
-
-            if (valueType.isAssignableFrom(nodeType)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    protected boolean verify(StructuredGraph graph) {
-        for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) {
-            Signature signature = graph.method().getSignature();
-            if (!(graph.method().getName().equals("equals") && signature.getParameterCount(false) == 1 && signature.getParameterKind(0).equals(Kind.Object))) {
-                assert !((checkType(cn.x()) && !(cn.y() instanceof ConstantNode)) || (checkType(cn.y()) && !(cn.x() instanceof ConstantNode))) : "VerifyValueUsage: " + cn.x() + " or " + cn.y() +
-                                " in " + graph.method() + " uses object identity. Should use equals() instead.";
-            }
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Thu May 23 14:44:01 2013 +0200
@@ -31,32 +31,33 @@
 
     @Test
     public void test0() {
-        test("lockObjectSimple", new Object(), new Object());
-        test("lockObjectSimple", new Object(), null);
+// test("lockObjectSimple", new Object(), new Object());
+// test("lockObjectSimple", new Object(), null);
+        test("lockObjectSimple", null, null);
     }
 
-    @Test
+    // @Test
     public void test0_1() {
         test("lockThisSimple", "test1", new Object());
         test("lockThisSimple", "test1", null);
     }
 
-    @Test
+    // @Test
     public void test0_2() {
         test("lockObjectSimple", null, "test1");
     }
 
-    @Test
+    // @Test
     public void test1_1() {
         test("lockObject", new Object(), "test1", new String[1]);
     }
 
-    @Test
+    // @Test
     public void test1_2() {
         test("lockObject", null, "test1_1", new String[1]);
     }
 
-    @Test
+    // @Test
     public void test2() {
         test("lockThis", "test2", new String[1]);
     }
@@ -64,7 +65,7 @@
     /**
      * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}.
      */
-    @Test
+    // @Test
     public void test3() {
         test("lockLocalObject", "test3", new String[1]);
     }
@@ -72,7 +73,7 @@
     /**
      * Tests recursive locking of objects which should be biasable.
      */
-    @Test
+    // @Test
     public void test4() {
         Chars src = new Chars("1234567890".toCharArray());
         Chars dst = new Chars(src.data.length);
@@ -82,7 +83,7 @@
     /**
      * Tests recursive locking of objects which do not appear to be biasable.
      */
-    @Test
+    // @Test
     public void test5() {
         char[] src = "1234567890".toCharArray();
         char[] dst = new char[src.length];
@@ -92,7 +93,7 @@
     /**
      * Extends {@link #test4()} with contention.
      */
-    @Test
+    // @Test
     public void test6() {
         Chars src = new Chars("1234567890".toCharArray());
         Chars dst = new Chars(src.data.length);
@@ -103,7 +104,7 @@
     /**
      * Extends {@link #test5()} with contention.
      */
-    @Test
+    // @Test
     public void test7() {
         char[] src = "1234567890".toCharArray();
         char[] dst = new char[src.length];
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Thu May 23 14:44:01 2013 +0200
@@ -33,7 +33,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.*;
 import com.oracle.graal.word.*;
@@ -43,7 +42,7 @@
  */
 public class PointerTest extends GraalCompilerTest implements Snippets {
 
-    private static final LocationIdentity ID = LocationNode.createLocation("ID");
+    private static final LocationIdentity ID = new NamedLocationIdentity("ID");
     private static final Kind[] KINDS = new Kind[]{Kind.Byte, Kind.Char, Kind.Short, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object};
     private final TargetDescription target;
     private final ReplacementsImpl installer;
@@ -78,7 +77,7 @@
     @Test
     public void test_read3() {
         for (Kind kind : KINDS) {
-            assertRead(parse("read" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION);
+            assertRead(parse("read" + kind.name() + "3"), kind, false, LocationIdentity.ANY_LOCATION);
         }
     }
 
@@ -99,7 +98,7 @@
     @Test
     public void test_write3() {
         for (Kind kind : KINDS) {
-            assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION);
+            assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationIdentity.ANY_LOCATION);
         }
     }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Thu May 23 14:44:01 2013 +0200
@@ -22,9 +22,11 @@
  */
 package com.oracle.graal.replacements.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.WriteNode.*;
+import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
@@ -62,7 +64,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph(), 1);
+        IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, value.kind(), displacement, offset, graph(), 1);
         WriteNode write = graph().add(new WriteNode(object, value, location, WriteBarrierType.NONE));
         graph().replaceFixedWithFixed(this, write);
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Thu May 23 14:44:01 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -33,7 +35,6 @@
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
@@ -173,7 +174,7 @@
                     for (LocationIdentity identity : checkpoint.getLocationIdentities()) {
                         if (identity instanceof ResolvedJavaField) {
                             state.killReadCache((ResolvedJavaField) identity);
-                        } else if (identity == LocationNode.ANY_LOCATION) {
+                        } else if (identity == ANY_LOCATION) {
                             state.killReadCache();
                         }
                     }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Thu May 23 14:44:01 2013 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.word;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 
 public interface Pointer extends Unsigned {
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Thu May 23 14:44:01 2013 +0200
@@ -27,10 +27,10 @@
 import java.lang.annotation.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 
 public abstract class Word implements Signed, Unsigned, Pointer {
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu May 23 14:44:01 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.word.phases;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.meta.*;
@@ -29,7 +31,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
@@ -164,7 +165,7 @@
                         Kind readKind = asKind(callTargetNode.returnType());
                         LocationNode location;
                         if (arguments.size() == 2) {
-                            location = makeLocation(graph, arguments.get(1), readKind, LocationNode.ANY_LOCATION);
+                            location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION);
                         } else {
                             location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2));
                         }
@@ -176,7 +177,7 @@
                         Kind writeKind = asKind(targetMethod.getSignature().getParameterType(1, targetMethod.getDeclaringClass()));
                         LocationNode location;
                         if (arguments.size() == 3) {
-                            location = makeLocation(graph, arguments.get(1), writeKind, LocationNode.ANY_LOCATION);
+                            location = makeLocation(graph, arguments.get(1), writeKind, LocationIdentity.ANY_LOCATION);
                         } else {
                             location = makeLocation(graph, arguments.get(1), writeKind, arguments.get(3));
                         }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Thu May 23 14:44:01 2013 +0200
@@ -115,7 +115,7 @@
      * @return the code as a String object
      */
     public final String getCode() {
-        return getSource().getCode().substring(charIndex, charLength);
+        return getSource().getCode().substring(charIndex, charIndex + charLength);
     }
 
     @Override
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Thu May 23 14:44:01 2013 +0200
@@ -149,6 +149,7 @@
             // Pass on the source section to the new node.
             newNode.assignSourceSection(sourceSection);
         }
+        onReplace(newNode, reason);
         return (T) this.getParent().replaceChild(this, newNode);
     }
 
@@ -170,6 +171,16 @@
     }
 
     /**
+     * Intended to be implemented by subclasses of {@link Node} to receive a notification when the
+     * node is rewritten. This method is invoked before the actual replace has happened.
+     * 
+     * @param newNode the replacement node
+     * @param reason the reason the replace supplied
+     */
+    protected void onReplace(Node newNode, String reason) {
+    }
+
+    /**
      * Invokes the {@link NodeVisitor#visit(Node)} method for this node and recursively also for all
      * child nodes.
      * 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java	Thu May 23 14:44:01 2013 +0200
@@ -37,4 +37,11 @@
      * @return the short name
      */
     String shortName() default "";
+
+    Kind kind() default Kind.SPECIALIZED;
+
+    public enum Kind {
+        UNINITIALIZED, SPECIALIZED, GENERIC
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java	Thu May 23 14:44:01 2013 +0200
@@ -26,7 +26,7 @@
 
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
-import javax.tools.Diagnostic.*;
+import javax.tools.Diagnostic.Kind;
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
@@ -47,6 +47,8 @@
     private final TypeMirror invalidAssumption;
     private final DeclaredType childAnnotation;
     private final DeclaredType childrenAnnotation;
+    private final DeclaredType nodeInfoAnnotation;
+    private final DeclaredType nodeInfoKind;
     private final TypeMirror compilerDirectives;
     private final TypeMirror compilerAsserts;
 
@@ -63,6 +65,12 @@
         compilerAsserts = getRequired(context, CompilerAsserts.class);
         assumption = getRequired(context, Assumption.class);
         invalidAssumption = getRequired(context, InvalidAssumptionException.class);
+        nodeInfoAnnotation = getRequired(context, NodeInfo.class);
+        nodeInfoKind = getRequired(context, NodeInfo.Kind.class);
+    }
+
+    public DeclaredType getNodeInfoAnnotation() {
+        return nodeInfoAnnotation;
     }
 
     public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) {
@@ -77,6 +85,10 @@
         return false;
     }
 
+    public DeclaredType getNodeInfoKind() {
+        return nodeInfoKind;
+    }
+
     private DeclaredType getRequired(ProcessorContext context, Class clazz) {
         TypeMirror type = context.getType(clazz);
         if (type == null) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Thu May 23 14:44:01 2013 +0200
@@ -40,6 +40,26 @@
  */
 public class Utils {
 
+    public static ExecutableElement findExecutableElement(DeclaredType type, String name) {
+        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
+        for (ExecutableElement executableElement : elements) {
+            if (executableElement.getSimpleName().toString().equals(name)) {
+                return executableElement;
+            }
+        }
+        return null;
+    }
+
+    public static VariableElement findVariableElement(DeclaredType type, String name) {
+        List<? extends VariableElement> elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements());
+        for (VariableElement variableElement : elements) {
+            if (variableElement.getSimpleName().toString().equals(name)) {
+                return variableElement;
+            }
+        }
+        return null;
+    }
+
     public static String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
         if (method instanceof CodeExecutableElement) {
             return ((CodeExecutableElement) method).getBody();
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.java	Thu May 23 14:44:01 2013 +0200
@@ -26,8 +26,8 @@
 
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
-import javax.lang.model.util.*;
 
+import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.api.element.*;
 
 public class CodeAnnotationMirror implements WritableAnnotationMirror {
@@ -60,13 +60,7 @@
     }
 
     public ExecutableElement findExecutableElement(String name) {
-        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(annotationType.asElement().getEnclosedElements());
-        for (ExecutableElement executableElement : elements) {
-            if (executableElement.getSimpleName().toString().equals(name)) {
-                return executableElement;
-            }
-        }
-        return null;
+        return Utils.findExecutableElement(annotationType, name);
     }
 
     public static CodeAnnotationMirror clone(AnnotationMirror mirror) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Thu May 23 14:44:01 2013 +0200
@@ -246,23 +246,7 @@
     }
 
     public CodeTreeBuilder doubleQuote(String s) {
-        return startGroup().string("\"").string(s).string("\"").end();
-    }
-
-    public CodeTreeBuilder startDoubleQuote() {
-        startGroup().string("\"");
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string("\"");
-            }
-        });
-        return this;
+        return startGroup().string("\"" + s + "\"").end();
     }
 
     public CodeTreeBuilder string(String chunk1) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java	Thu May 23 14:44:01 2013 +0200
@@ -75,23 +75,6 @@
         return count;
     }
 
-    public boolean startsWithSignature(TemplateMethod method) {
-        for (ActualParameter param : getParameters()) {
-            if (!param.getSpecification().isSignature()) {
-                continue;
-            }
-            ActualParameter foundParam = method.findParameter(param.getLocalName());
-            if (foundParam != null) {
-                TypeData actualType = param.getTypeSystemType();
-                TypeData foundType = foundParam.getTypeSystemType();
-                if (actualType == null || foundType == null || !actualType.equalsType(foundType)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
     public boolean hasGenericSignature() {
         List<TypeData> types = getSignature();
         for (TypeData typeData : types) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java	Thu May 23 14:44:01 2013 +0200
@@ -44,8 +44,15 @@
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null);
+        List<ParameterSpec> requiredSpecs = new ArrayList<>(spec.getRequired());
+        spec.getRequired().clear();
+
+        for (ParameterSpec originalSpec : requiredSpecs) {
+            spec.addRequired(new ParameterSpec(originalSpec, Arrays.asList(getNode().getTypeSystem().getGenericType())));
+        }
+
         spec.setVariableRequiredArguments(true);
-        ParameterSpec other = new ParameterSpec("other", nodeTypeMirrors(getNode()));
+        ParameterSpec other = new ParameterSpec("other", Arrays.asList(getNode().getTypeSystem().getGenericType()));
         other.setCardinality(Cardinality.MANY);
         other.setSignature(true);
         other.setIndexed(true);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Thu May 23 14:44:01 2013 +0200
@@ -766,10 +766,55 @@
                 }
                 builder.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end();
                 prefix = null;
+
+                builder.startStatement().string("StringBuilder message = new StringBuilder(reason)").end();
+                builder.startStatement().startCall("message", "append").doubleQuote(" (").end().end();
+
+                String sep = null;
+                for (ActualParameter parameter : node.getGenericSpecialization().getParameters()) {
+                    if (!parameter.getSpecification().isSignature()) {
+                        continue;
+                    }
+
+                    builder.startStatement();
+                    builder.string("message");
+                    if (sep != null) {
+                        builder.startCall(".append").doubleQuote(sep).end();
+                    }
+                    builder.startCall(".append").doubleQuote(parameter.getLocalName()).end();
+                    builder.startCall(".append").doubleQuote(" = ").end();
+                    builder.startCall(".append").string(parameter.getLocalName()).end();
+                    builder.end();
+
+                    if (!Utils.isPrimitive(parameter.getType())) {
+                        builder.startIf().string(parameter.getLocalName() + " != null").end();
+                        builder.startBlock();
+                    }
+                    builder.startStatement();
+                    if (Utils.isPrimitive(parameter.getType())) {
+                        builder.startCall("message.append").doubleQuote(" (" + Utils.getSimpleName(parameter.getType()) + ")").end();
+                    } else {
+                        builder.startCall("message.append").doubleQuote(" (").end();
+                        builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end();
+                        builder.startCall(".append").doubleQuote(")").end();
+                    }
+                    builder.end();
+                    if (!Utils.isPrimitive(parameter.getType())) {
+                        builder.end();
+                    }
+
+                    sep = ", ";
+                }
+
+                builder.startStatement().startCall("message", "append").doubleQuote(")").end().end();
             }
 
             addInternalValueParameters(method, node.getGenericSpecialization(), true);
 
+            if (specialize) {
+                method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
+            }
+
             List<SpecializationData> specializations = node.getSpecializations();
             if (!specialize && !node.getGenericSpecialization().isUseSpecializationsForGeneric()) {
                 specializations = Arrays.asList(node.getGenericSpecialization());
@@ -864,6 +909,7 @@
 
                 builder.startStatement().startCall("super", "replace");
                 builder.startGroup().startNew(nodeSpecializationClassName(current)).string("this").end().end();
+                builder.string("message.toString()");
                 builder.end().end();
 
                 if (current.getReturnSignature().isVoid()) {
@@ -1336,6 +1382,27 @@
                 baseType = nodeGen.asType();
             }
             CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
+
+            String shortName = specialization.getNode().getShortName();
+            CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
+            if (shortName != null) {
+                nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName));
+            }
+
+            DeclaredType nodeinfoKind = getContext().getTruffleTypes().getNodeInfoKind();
+            VariableElement kind;
+            if (specialization.isGeneric()) {
+                kind = Utils.findVariableElement(nodeinfoKind, "GENERIC");
+            } else if (specialization.isUninitialized()) {
+                kind = Utils.findVariableElement(nodeinfoKind, "UNINITIALIZED");
+            } else {
+                kind = Utils.findVariableElement(nodeinfoKind, "SPECIALIZED");
+            }
+
+            nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("kind"), new CodeAnnotationValue(kind));
+
+            clazz.getAnnotationMirrors().add(nodeInfoMirror);
+
             return clazz;
         }
 
@@ -1373,12 +1440,13 @@
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
 
-            ExecutableTypeData foundEvaluatedPrimaryType = findFunctionalExecutableType(specialization, execType.getEvaluatedCount());
+            List<ExecutableTypeData> primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount());
 
-            if (execType == foundEvaluatedPrimaryType || foundEvaluatedPrimaryType == null) {
+            if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) {
                 builder.tree(createFunctionalExecute(builder, specialization, execType));
             } else if (needsCastingExecuteMethod(execType, primaryType)) {
-                builder.tree(createCastingExecute(builder, specialization, execType, foundEvaluatedPrimaryType));
+                assert !primaryExecutes.isEmpty();
+                builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0)));
             } else {
                 return null;
             }
@@ -1420,7 +1488,7 @@
             return false;
         }
 
-        private ExecutableTypeData findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) {
+        private List<ExecutableTypeData> findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) {
             TypeData primaryType = specialization.getReturnType().getTypeSystemType();
             List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount);
 
@@ -1432,19 +1500,24 @@
                 filteredTypes.add(compareType);
             }
 
-            for (ExecutableTypeData compareType : filteredTypes) {
-                if (compareType.startsWithSignature(specialization)) {
-                    return compareType;
+            // no direct matches found use generic where the type is Object
+            if (filteredTypes.isEmpty()) {
+                for (ExecutableTypeData compareType : otherTypes) {
+                    if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) {
+                        filteredTypes.add(compareType);
+                    }
                 }
             }
 
-            for (ExecutableTypeData compareType : otherTypes) {
-                if (compareType.startsWithSignature(specialization)) {
-                    return compareType;
+            if (filteredTypes.isEmpty()) {
+                for (ExecutableTypeData compareType : otherTypes) {
+                    if (compareType.getType().isGeneric()) {
+                        filteredTypes.add(compareType);
+                    }
                 }
             }
 
-            return null;
+            return filteredTypes;
         }
 
         private CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
@@ -1558,7 +1631,7 @@
             if (next != null) {
                 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
                 returnBuilder.tree(createDeoptimize(builder));
-                returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null));
+                returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null, "One of guards " + specialization.getGuards() + " failed"));
                 returnSpecialized = returnBuilder.getRoot();
             }
             builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false));
@@ -1592,6 +1665,7 @@
                 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME);
                 returnBuilder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end();
                 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
+                returnBuilder.doubleQuote("Uninitialized");
                 returnBuilder.end();
             } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
                 emitEncounteredSynthetic(builder);
@@ -1623,13 +1697,13 @@
                 for (SpecializationThrowsData exception : specialization.getExceptions()) {
                     builder.end().startCatchBlock(exception.getJavaClass(), "ex");
                     builder.tree(createDeoptimize(builder));
-                    builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null));
+                    builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null, "Thrown " + Utils.getSimpleName(exception.getJavaClass())));
                 }
                 builder.end();
             }
             if (!specialization.getAssumptions().isEmpty()) {
                 builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
-                builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null));
+                builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null, "Assumption failed"));
                 builder.end();
             }
 
@@ -1734,7 +1808,8 @@
                 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter);
                 builder.tree(createDeoptimize(builder));
                 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false));
-                builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param));
+                builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param,
+                                "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType())));
                 builder.end(); // catch block
             }
 
@@ -1850,13 +1925,14 @@
             return builder.getRoot();
         }
 
-        private CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam) {
+        private CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam, String reason) {
 
             SpecializationData generic = nextSpecialization.getNode().getGenericSpecialization();
             CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
             specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
             specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class");
             addInternalValueParameterNames(specializeCall, generic, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true);
+            specializeCall.doubleQuote(reason);
             specializeCall.end().end();
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Thu May 23 14:44:01 2013 +0200
@@ -51,6 +51,8 @@
     private List<ShortCircuitData> shortCircuits;
     private List<String> assumptions;
 
+    private String shortName;
+
     public NodeData(TypeElement type, String id) {
         super(type, null, null);
         this.nodeId = id;
@@ -72,6 +74,14 @@
         this.assumptions = splitSource.assumptions;
     }
 
+    void setShortName(String shortName) {
+        this.shortName = shortName;
+    }
+
+    public String getShortName() {
+        return shortName;
+    }
+
     public boolean isSplitByMethodName() {
         return splitByMethodName;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Thu May 23 14:44:01 2013 +0200
@@ -32,6 +32,7 @@
 
 import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.api.codegen.NodeClass.InheritNode;
+import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality;
 import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind;
@@ -577,6 +578,11 @@
                 }
             }
         }
+        AnnotationMirror nodeInfoMirror = findFirstAnnotation(lookupTypes, NodeInfo.class);
+        if (nodeInfoMirror != null) {
+            nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"));
+        }
+
         nodeData.setAssumptions(new ArrayList<>(assumptionsList));
         nodeData.setNodeType(nodeType);
         nodeData.setSplitByMethodName(splitByMethodName);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Thu May 23 14:44:01 2013 +0200
@@ -55,6 +55,16 @@
         this.allowedTypes = allowedTypes;
     }
 
+    public ParameterSpec(ParameterSpec o, List<TypeMirror> allowedTypes) {
+        this.name = o.name;
+        this.cardinality = o.cardinality;
+        this.signature = o.signature;
+        this.indexed = o.indexed;
+        this.local = o.local;
+        this.typeDefinition = o.typeDefinition;
+        this.allowedTypes = allowedTypes;
+    }
+
     void setTypeDefinition(TypeDef typeDefinition) {
         this.typeDefinition = typeDefinition;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java	Fri May 17 16:47:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java	Thu May 23 14:44:01 2013 +0200
@@ -38,4 +38,9 @@
         return specialization;
     }
 
+    @Override
+    public String toString() {
+        return getMethodName();
+    }
+
 }
--- a/mx/commands.py	Fri May 17 16:47:13 2013 +0200
+++ b/mx/commands.py	Thu May 23 14:44:01 2013 +0200
@@ -825,7 +825,7 @@
     def harness(projectscp, vmArgs):
         if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource):
             subprocess.check_call([mx.java().javac, '-cp', projectscp, '-d', mxdir, javaSource])
-        if _vm == 'original' or _vm.endswith('nograal'):
+        if not isGraalEnabled(_vm):
             prefixArgs = ['-esa', '-ea']
         else:
             prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea']
@@ -1333,6 +1333,9 @@
         mx.abort('jacocoreport takes only one argument : an output directory')
     mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out])
 
+def isGraalEnabled(vm):
+    return vm != 'original' and not vm.endswith('nograal')
+
 def site(args):
     """create a website containing javadoc and the project dependency graph"""
 
--- a/mx/sanitycheck.py	Fri May 17 16:47:13 2013 +0200
+++ b/mx/sanitycheck.py	Thu May 23 14:44:01 2013 +0200
@@ -235,15 +235,15 @@
 
     
     args = ['-XX:+CompileTheWorld', '-Xbootclasspath/p:' + rtjar]
-    if not vm.endswith('-nograal'):
+    if commands.isGraalEnabled(vm):
         args += ['-XX:+BootstrapGraal', '-G:-Debug']
     if mode >= CTWMode.NoInline:
-        if vm.endswith('-nograal'):
+        if not commands.isGraalEnabled(vm):
             args.append('-XX:-Inline')
         else:
             args.append('-G:-Inline')
     if mode >= CTWMode.NoComplex:
-        if not vm.endswith('-nograal'):
+        if commands.isGraalEnabled(vm):
             args += ['-G:-OptLoopTransform', '-G:-OptTailDuplication', '-G:-FullUnroll', '-G:-MemoryAwareScheduling', '-G:-PartialEscapeAnalysis']
         
     return Test("CompileTheWorld", args, successREs=[time], scoreMatchers=[scoreMatcher], benchmarkCompilationRate=False)
--- a/src/cpu/sparc/vm/c2_globals_sparc.hpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp	Thu May 23 14:44:01 2013 +0200
@@ -38,6 +38,7 @@
 define_pd_global(bool, ProfileTraps,                 true);
 define_pd_global(bool, UseOnStackReplacement,        true);
 define_pd_global(intx, TypeProfileWidth,             2   );
+define_pd_global(intx, MethodProfileWidth,           0   );
 #ifdef CC_INTERP
 define_pd_global(bool, ProfileInterpreter,           false);
 #else
--- a/src/cpu/x86/vm/c1_globals_x86.hpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/cpu/x86/vm/c1_globals_x86.hpp	Thu May 23 14:44:01 2013 +0200
@@ -56,6 +56,7 @@
 define_pd_global(uint64_t,MaxRAM,                    1ULL*G);
 define_pd_global(bool, CICompileOSR,                 true );
 define_pd_global(intx, TypeProfileWidth,             0);
+define_pd_global(intx, MethodProfileWidth,           0);
 #endif // !TIERED
 define_pd_global(bool, UseTypeProfile,               false);
 define_pd_global(bool, RoundFPResults,               true );
--- a/src/cpu/x86/vm/c2_globals_x86.hpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/cpu/x86/vm/c2_globals_x86.hpp	Thu May 23 14:44:01 2013 +0200
@@ -40,6 +40,7 @@
 define_pd_global(bool, ProfileTraps,                 true);
 define_pd_global(bool, UseOnStackReplacement,        true);
 define_pd_global(intx, TypeProfileWidth,             2   );
+define_pd_global(intx, MethodProfileWidth,           0   );
 #ifdef CC_INTERP
 define_pd_global(bool, ProfileInterpreter,           false);
 #else
--- a/src/cpu/x86/vm/graalGlobals_x86.hpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/cpu/x86/vm/graalGlobals_x86.hpp	Thu May 23 14:44:01 2013 +0200
@@ -58,6 +58,7 @@
 define_pd_global(intx, CodeCacheExpansionSize,       64*K );
 define_pd_global(uintx,CodeCacheMinBlockLength,      4);
 define_pd_global(intx, TypeProfileWidth,             8);
+define_pd_global(intx, MethodProfileWidth,           4);
 #endif
 
 #endif // CPU_X86_VM_GRAALGLOBALS_X86_HPP
--- a/src/cpu/x86/vm/interp_masm_x86_64.cpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp	Thu May 23 14:44:01 2013 +0200
@@ -1082,9 +1082,10 @@
     increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
 
     // The method data pointer needs to be updated to reflect the new target.
-    update_mdp_by_constant(mdp,
-                           in_bytes(VirtualCallData::
+    update_mdp_by_constant(mdp,
+                           in_bytes(VirtualCallData::
                                     virtual_call_data_size()));
+
     bind(profile_continue);
   }
 }
@@ -1116,13 +1117,38 @@
     bind(skip_receiver_profile);
 
     // The method data pointer needs to be updated to reflect the new target.
-    update_mdp_by_constant(mdp,
-                           in_bytes(VirtualCallData::
-                                    virtual_call_data_size()));
+#ifdef GRAAL
+    if (MethodProfileWidth == 0) {
+      update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
+    }
+#else
+    update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
+#endif
     bind(profile_continue);
   }
 }
 
+#ifdef GRAAL
+void InterpreterMacroAssembler::profile_called_method(Register method, Register mdp, Register reg2) {
+  assert_different_registers(method, mdp, reg2);
+  if (ProfileInterpreter && MethodProfileWidth > 0) {
+    Label profile_continue;
+
+    // If no method data exists, go to profile_continue.
+    test_method_data_pointer(mdp, profile_continue);
+    
+    Label done;
+    record_item_in_profile_helper(method, mdp, reg2, 0, done, MethodProfileWidth,
+      &VirtualCallData::method_offset, &VirtualCallData::method_count_offset, in_bytes(VirtualCallData::nonprofiled_receiver_count_offset()));
+    bind (done);
+
+    update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
+    bind(profile_continue);
+  }
+}
+
+#endif
+
 // This routine creates a state machine for updating the multi-row
 // type profile at a virtual call site (or other type-sensitive bytecode).
 // The machine visits each row (of receiver/count) until the receiver type
@@ -1136,8 +1162,7 @@
 // See below for example code.
 void InterpreterMacroAssembler::record_klass_in_profile_helper(
                                         Register receiver, Register mdp,
-                                        Register reg2, int start_row,
-                                        Label& done, bool is_virtual_call) {
+                                        Register reg2, Label& done, bool is_virtual_call) {
   if (TypeProfileWidth == 0) {
     if (is_virtual_call) {
       increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
@@ -1147,14 +1172,33 @@
       increment_mdp_data_at(mdp, in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset()));
     }
 #endif
-    return;
-  }
+  } else {                                      
+    bool use_non_profiled_counter = !is_virtual_call || IS_GRAAL_DEFINED;
+    int non_profiled_offset = -1;
+    if (use_non_profiled_counter) {
+       non_profiled_offset = in_bytes(CounterData::count_offset());
+    #ifdef GRAAL
+      if (!is_virtual_call) {
+        non_profiled_offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset());
+      }
+    #endif
+      assert(non_profiled_offset >= 0, "must be");
+    }
 
-  int last_row = VirtualCallData::row_limit() - 1;
+    record_item_in_profile_helper(receiver, mdp, reg2, 0, done, TypeProfileWidth,
+      &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset, non_profiled_offset);
+  }
+}
+
+void InterpreterMacroAssembler::record_item_in_profile_helper(Register item, Register mdp,
+                                        Register reg2, int start_row, Label& done, int total_rows,
+                                        OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+                                        int non_profiled_offset) {
+  int last_row = total_rows - 1;
   assert(start_row <= last_row, "must be work left to do");
-  // Test this row for both the receiver and for null.
+  // Test this row for both the item and for null.
   // Take any of three different outcomes:
-  //   1. found receiver => increment count and goto done
+  //   1. found item => increment count and goto done
   //   2. found null => keep looking for case 1, maybe allocate this cell
   //   3. found something else => keep looking for cases 1 and 2
   // Case 3 is handled by a recursive call.
@@ -1162,36 +1206,30 @@
     Label next_test;
     bool test_for_null_also = (row == start_row);
 
-    // See if the receiver is receiver[n].
-    int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row));
-    test_mdp_data_at(mdp, recvr_offset, receiver,
+    // See if the item is item[n].
+    int item_offset = in_bytes(item_offset_fn(row));
+    test_mdp_data_at(mdp, item_offset, item,
                      (test_for_null_also ? reg2 : noreg),
                      next_test);
-    // (Reg2 now contains the receiver from the CallData.)
+    // (Reg2 now contains the item from the CallData.)
 
-    // The receiver is receiver[n].  Increment count[n].
-    int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row));
+    // The item is item[n].  Increment count[n].
+    int count_offset = in_bytes(item_count_offset_fn(row));
     increment_mdp_data_at(mdp, count_offset);
     jmp(done);
     bind(next_test);
 
     if (test_for_null_also) {
       Label found_null;
-      // Failed the equality check on receiver[n]...  Test for null.
+      // Failed the equality check on item[n]...  Test for null.
       testptr(reg2, reg2);
       if (start_row == last_row) {
         // The only thing left to do is handle the null case.
-        if (is_virtual_call GRAAL_ONLY(|| true)) {
+        if (non_profiled_offset >= 0) {
           jccb(Assembler::zero, found_null);
-          // Receiver did not match any saved receiver and there is no empty row for it.
+          // Item did not match any saved item and there is no empty row for it.
           // Increment total counter to indicate polymorphic case.
-          int offset = in_bytes(CounterData::count_offset());
-#ifdef GRAAL
-          if (!is_virtual_call) {
-            offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset());
-          }
-#endif
-          increment_mdp_data_at(mdp, offset);
+          increment_mdp_data_at(mdp, non_profiled_offset);
           jmp(done);
           bind(found_null);
         } else {
@@ -1203,21 +1241,22 @@
       jcc(Assembler::zero, found_null);
 
       // Put all the "Case 3" tests here.
-      record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call);
+      record_item_in_profile_helper(item, mdp, reg2, start_row + 1, done, total_rows,
+        item_offset_fn, item_count_offset_fn, non_profiled_offset);
 
-      // Found a null.  Keep searching for a matching receiver,
+      // Found a null.  Keep searching for a matching item,
       // but remember that this is an empty (unused) slot.
       bind(found_null);
     }
   }
 
-  // In the fall-through case, we found no matching receiver, but we
-  // observed the receiver[start_row] is NULL.
+  // In the fall-through case, we found no matching item, but we
+  // observed the item[start_row] is NULL.
 
-  // Fill in the receiver field and increment the count.
-  int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row));
-  set_mdp_data_at(mdp, recvr_offset, receiver);
-  int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row));
+  // Fill in the item field and increment the count.
+  int item_offset = in_bytes(item_offset_fn(start_row));
+  set_mdp_data_at(mdp, item_offset, item);
+  int count_offset = in_bytes(item_count_offset_fn(start_row));
   movl(reg2, DataLayout::counter_increment);
   set_mdp_data_at(mdp, count_offset, reg2);
   if (start_row > 0) {
@@ -1255,7 +1294,7 @@
   assert(ProfileInterpreter, "must be profiling");
   Label done;
 
-  record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call);
+  record_klass_in_profile_helper(receiver, mdp, reg2, done, is_virtual_call);
 
   bind (done);
 }
@@ -1310,7 +1349,7 @@
     // The method data pointer needs to be updated.
     int mdp_delta = in_bytes(BitData::bit_data_size());
     if (TypeProfileCasts) {
-      mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
+      mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
     }
     update_mdp_by_constant(mdp, mdp_delta);
 
@@ -1328,7 +1367,7 @@
 
     int count_offset = in_bytes(CounterData::count_offset());
     // Back up the address, since we have already bumped the mdp.
-    count_offset -= in_bytes(VirtualCallData::virtual_call_data_size());
+    count_offset -= in_bytes(ReceiverTypeData::receiver_type_data_size());
 
     // *Decrement* the counter.  We expect to see zero or small negatives.
     increment_mdp_data_at(mdp, count_offset, true);
@@ -1348,7 +1387,7 @@
     // The method data pointer needs to be updated.
     int mdp_delta = in_bytes(BitData::bit_data_size());
     if (TypeProfileCasts) {
-      mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
+      mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
 
       // Record the object type.
       record_klass_in_profile(klass, mdp, reg2, false);
--- a/src/cpu/x86/vm/interp_masm_x86_64.hpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/cpu/x86/vm/interp_masm_x86_64.hpp	Thu May 23 14:44:01 2013 +0200
@@ -32,6 +32,7 @@
 
 // This file specializes the assember with interpreter-specific macros
 
+typedef ByteSize (*OffsetFunction)(uint);
 
 class InterpreterMacroAssembler: public MacroAssembler {
 #ifndef CC_INTERP
@@ -213,8 +214,11 @@
   void record_klass_in_profile(Register receiver, Register mdp,
                                Register reg2, bool is_virtual_call);
   void record_klass_in_profile_helper(Register receiver, Register mdp,
-                                      Register reg2, int start_row,
-                                      Label& done, bool is_virtual_call);
+                                      Register reg2, Label& done, bool is_virtual_call);
+  void record_item_in_profile_helper(Register item, Register mdp,
+                                        Register reg2, int start_row, Label& done, int total_rows,
+                                        OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+                                        int non_profiled_offset);
 
   void update_mdp_by_offset(Register mdp_in, int offset_of_offset);
   void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp);
@@ -228,6 +232,7 @@
   void profile_virtual_call(Register receiver, Register mdp,
                             Register scratch2,
                             bool receiver_can_be_null = false);
+  void profile_called_method(Register method, Register mdp, Register reg2);
   void profile_ret(Register return_bci, Register mdp);
   void profile_null_seen(Register mdp);
   void profile_typecheck(Register mdp, Register klass, Register scratch);
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/cpu/x86/vm/templateTable_x86_64.cpp	Thu May 23 14:44:01 2013 +0200
@@ -3017,6 +3017,10 @@
 
   // get target Method* & entry point
   __ lookup_virtual_method(rax, index, method);
+#ifdef GRAAL
+  // r14: MethodDataPointer (r14 is callee saved)
+  __ profile_called_method(method, r14, r13);
+#endif
   __ jump_from_interpreted(method, rdx);
 }
 
@@ -3101,7 +3105,7 @@
   __ lookup_interface_method(// inputs: rec. class, interface, itable index
                              rdx, rax, rbx,
                              // outputs: method, scan temp. reg
-                             rbx, r13,
+                             rbx, r14,
                              no_such_interface);
 
   // rbx: Method* to call
@@ -3116,6 +3120,10 @@
   // do the call
   // rcx: receiver
   // rbx,: Method*
+#ifdef GRAAL
+  // r13: MethodDataPointer (r13 is callee saved)
+  __ profile_called_method(rbx, r13, r14);
+#endif
   __ jump_from_interpreted(rbx, rdx);
   __ should_not_reach_here();
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu May 23 14:44:01 2013 +0200
@@ -687,6 +687,8 @@
   set_int("methodMaxLocalsOffset", in_bytes(ConstMethod::size_of_locals_offset()));
   set_int("methodConstMethodOffset", in_bytes(Method::const_offset()));
   set_int("constMethodMaxStackOffset", in_bytes(ConstMethod::max_stack_offset()));
+  set_int("constMethodConstantsOffset", in_bytes(ConstMethod::constants_offset()));
+  set_int("constantPoolHolderOffset", ConstantPool::pool_holder_offset_in_bytes());
   set_int("extraStackEntries", Method::extra_stack_entries());
   set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset()));
   set_int("methodIntrinsicIdOffset", Method::intrinsic_id_offset_in_bytes());
@@ -730,6 +732,7 @@
   set_int("dataLayoutCellSize", DataLayout::cell_size);
   set_int("bciProfileWidth", BciProfileWidth);
   set_int("typeProfileWidth", TypeProfileWidth);
+  set_int("methodProfileWidth", MethodProfileWidth);
 
   set_int("tlabAlignmentReserve", (int32_t)ThreadLocalAllocBuffer::alignment_reserve());
   set_long("tlabIntArrayMarkWord", (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2));
--- a/src/share/vm/oops/methodData.cpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/share/vm/oops/methodData.cpp	Thu May 23 14:44:01 2013 +0200
@@ -168,6 +168,18 @@
   }
 }
 
+#ifdef GRAAL
+void VirtualCallData::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
+  ReceiverTypeData::clean_weak_klass_links(is_alive_cl);
+  for (uint row = 0; row < method_row_limit(); row++) {
+    Method* p = method(row);
+    if (p != NULL && !p->method_holder()->is_loader_alive(is_alive_cl)) {
+      clear_method_row(row);
+    }
+  }
+}
+#endif // GRAAL
+
 #ifndef PRODUCT
 void ReceiverTypeData::print_receiver_data_on(outputStream* st) {
   uint row;
--- a/src/share/vm/oops/methodData.hpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/share/vm/oops/methodData.hpp	Thu May 23 14:44:01 2013 +0200
@@ -635,9 +635,17 @@
 protected:
   enum {
 #ifdef GRAAL
-    // Graal is interested in knowing the percentage of type checks
-    // involving a type not explicitly in the profile
-    nonprofiled_receiver_count_off_set = counter_cell_count,
+    // Description of the different counters
+    // ReceiverTypeData for instanceof/checkcast/aastore:
+    //   C1/C2: count is incremented on type overflow and decremented for failed type checks
+    //   Graal: count decremented for failed type checks and nonprofiled_count is incremented on type overflow
+    //          TODO (chaeubl): in fact, Graal should also increment the count for failed type checks to mimic the C1/C2 behavior
+    // VirtualCallData for invokevirtual/invokeinterface:
+    //   C1/C2: count is incremented on type overflow
+    //   Graal: count is incremented on type overflow, nonprofiled_count is increment on method overflow
+
+    // Graal is interested in knowing the percentage of type checks involving a type not explicitly in the profile
+    nonprofiled_count_off_set = counter_cell_count,
     receiver0_offset,
 #else
     receiver0_offset = counter_cell_count,
@@ -717,6 +725,13 @@
     set_count(0);
     set_receiver(row, NULL);
     set_receiver_count(row, 0);
+#ifdef GRAAL
+    if (!this->is_VirtualCallData()) {
+      // if this is a ReceiverTypeData for Graal, the nonprofiled_count
+      // must also be reset (see "Description of the different counters" above)
+      set_nonprofiled_count(0);
+    }
+#endif
   }
 
   // Code generation support
@@ -728,7 +743,10 @@
   }
 #ifdef GRAAL
   static ByteSize nonprofiled_receiver_count_offset() {
-    return cell_offset(nonprofiled_receiver_count_off_set);
+    return cell_offset(nonprofiled_count_off_set);
+  }
+  void set_nonprofiled_count(uint count) {
+    set_uint_at(nonprofiled_count_off_set, count);
   }
 #endif
   static ByteSize receiver_type_data_size() {
@@ -759,7 +777,7 @@
   static int static_cell_count() {
     // At this point we could add more profile state, e.g., for arguments.
     // But for now it's the same size as the base record type.
-    return ReceiverTypeData::static_cell_count();
+    return ReceiverTypeData::static_cell_count() GRAAL_ONLY(+ (uint) MethodProfileWidth * receiver_type_row_cell_count);
   }
 
   virtual int cell_count() {
@@ -771,6 +789,53 @@
     return cell_offset(static_cell_count());
   }
 
+#ifdef GRAAL
+  static ByteSize method_offset(uint row) {
+    return cell_offset(method_cell_index(row));
+  }
+  static ByteSize method_count_offset(uint row) {
+    return cell_offset(method_count_cell_index(row));
+  }
+  static int method_cell_index(uint row) {
+    return receiver0_offset + (row + TypeProfileWidth) * receiver_type_row_cell_count;
+  }
+  static int method_count_cell_index(uint row) {
+    return count0_offset + (row + TypeProfileWidth) * receiver_type_row_cell_count;
+  }
+  static uint method_row_limit() {
+    return MethodProfileWidth;
+  }
+
+  Method* method(uint row) {
+    assert(row < method_row_limit(), "oob");
+
+    Method* method = (Method*)intptr_at(method_cell_index(row));
+    assert(method == NULL || method->is_method(), "must be");
+    return method;
+  }
+
+  void set_method(uint row, Method* m) {
+    assert((uint)row < method_row_limit(), "oob");
+    set_intptr_at(method_cell_index(row), (uintptr_t)m);
+  }
+
+  void set_method_count(uint row, uint count) {
+    assert(row < method_row_limit(), "oob");
+    set_uint_at(method_count_cell_index(row), count);
+  }
+
+  void clear_method_row(uint row) {
+    assert(row < method_row_limit(), "oob");
+    // Clear total count - indicator of polymorphic call site (see comment for clear_row() in ReceiverTypeData).
+    set_nonprofiled_count(0);
+    set_method(row, NULL);
+    set_method_count(row, 0);
+  }
+
+  // GC support
+  virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
+#endif
+
 #ifndef PRODUCT
   void print_data_on(outputStream* st);
 #endif
--- a/src/share/vm/runtime/globals.hpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/share/vm/runtime/globals.hpp	Thu May 23 14:44:01 2013 +0200
@@ -2949,6 +2949,9 @@
   product_pd(intx, TypeProfileWidth,                                        \
           "number of receiver types to record in call/cast profile")        \
                                                                             \
+  product_pd(intx, MethodProfileWidth,                                      \
+          "number of methods to record in call profile")                    \
+                                                                            \
   develop(intx, BciProfileWidth,      2,                                    \
           "number of return bci's to record in ret profile")                \
                                                                             \
--- a/src/share/vm/utilities/macros.hpp	Fri May 17 16:47:13 2013 +0200
+++ b/src/share/vm/utilities/macros.hpp	Thu May 23 14:44:01 2013 +0200
@@ -182,6 +182,7 @@
 #ifdef GRAAL
 #define GRAAL_ONLY(code) code
 #define NOT_GRAAL(code)
+#define IS_GRAAL_DEFINED true
 #if !defined(COMPILER1) && !defined(COMPILER2)
 // Graal is the only compiler in the system and so will be used for compilation
 // requests issued by the compile broker.
@@ -197,6 +198,7 @@
 #else // !GRAAL
 #define GRAAL_ONLY(code)
 #define NOT_GRAAL(code) code
+#define IS_GRAAL_DEFINED false
 #define GRAALVM_ONLY(code)
 #define NOT_GRAALVM(code) code
 #endif // GRAAL