changeset 16526:446750355e5f

Merge
author Stefan Anzinger <stefan.anzinger@gmail.com>
date Tue, 15 Jul 2014 19:21:28 -0700
parents 072b9501f5f9 (current diff) d6ac7470603e (diff)
children 22ae26714321
files graal/com.oracle.graal.api.meta.jdk8.test/src/com/oracle/graal/api/meta/jdk8/test/TestResolvedJavaMethodJDK8.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java
diffstat 221 files changed, 2853 insertions(+), 2393 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.api.code;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 import java.io.*;
 import java.lang.invoke.*;
 import java.util.*;
@@ -71,7 +69,7 @@
 
         @Override
         public String toString() {
-            return "NoFinalizableSubclass[receiverType=" + toJavaName(receiverType) + "]";
+            return "NoFinalizableSubclass[receiverType=" + receiverType.toJavaName() + "]";
         }
 
     }
@@ -97,7 +95,7 @@
             this.context = context;
             this.subtype = subtype;
             assert !subtype.isAbstract() : subtype.toString() + " : " + context.toString();
-            assert !subtype.isArray() || getElementalType(subtype).isFinal() : subtype.toString() + " : " + context.toString();
+            assert !subtype.isArray() || subtype.getElementalType().isFinal() : subtype.toString() + " : " + context.toString();
         }
 
         @Override
@@ -120,7 +118,7 @@
 
         @Override
         public String toString() {
-            return "ConcreteSubtype[context=" + toJavaName(context) + ", subtype=" + toJavaName(subtype) + "]";
+            return "ConcreteSubtype[context=" + context.toJavaName() + ", subtype=" + subtype.toJavaName() + "]";
         }
     }
 
@@ -174,7 +172,7 @@
 
         @Override
         public String toString() {
-            return "ConcreteMethod[method=" + format("%H.%n(%p)", method) + ", context=" + toJavaName(context) + ", impl=" + format("%H.%n(%p)", impl) + "]";
+            return "ConcreteMethod[method=" + method.format("%H.%n(%p)") + ", context=" + context.toJavaName() + ", impl=" + impl.format("%H.%n(%p)") + "]";
         }
     }
 
@@ -207,7 +205,7 @@
 
         @Override
         public String toString() {
-            return "MethodContents[method=" + format("%H.%n(%p)", method) + "]";
+            return "MethodContents[method=" + method.format("%H.%n(%p)") + "]";
         }
     }
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.api.code;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -153,6 +152,6 @@
      * @return true if {@code type} can have subtypes
      */
     public static boolean canHaveSubtype(ResolvedJavaType type) {
-        return !getElementalType(type).isFinal();
+        return !type.getElementalType().isFinal();
     }
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.api.code;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -70,7 +68,7 @@
     private static StringBuilder appendValue(StringBuilder buf, Value value, Set<VirtualObject> visited) {
         if (value instanceof VirtualObject) {
             VirtualObject vo = (VirtualObject) value;
-            buf.append("vobject:").append(toJavaName(vo.type, false)).append(':').append(vo.id);
+            buf.append("vobject:").append(vo.type.toJavaName(false)).append(':').append(vo.id);
             if (!visited.contains(vo)) {
                 visited.add(vo);
                 buf.append('{');
--- a/graal/com.oracle.graal.api.meta.jdk8.test/src/com/oracle/graal/api/meta/jdk8/test/TestResolvedJavaMethodJDK8.java	Tue Jul 15 19:15:46 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +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.api.meta.jdk8.test;
-
-import static org.junit.Assert.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.test.*;
-
-/**
- * Tests for {@link ResolvedJavaMethod} that require JDK &ge; 8.
- */
-public class TestResolvedJavaMethodJDK8 extends MethodUniverse {
-
-    public TestResolvedJavaMethodJDK8() {
-    }
-
-    @Test
-    public void isDefaultTest() {
-        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
-            ResolvedJavaMethod m = e.getValue();
-            assertEquals(e.getKey().isDefault(), m.isDefault());
-        }
-        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
-            ResolvedJavaMethod m = e.getValue();
-            assertFalse(m.isDefault());
-        }
-    }
-}
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/ResolvedJavaTypeResolveMethodTest.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/ResolvedJavaTypeResolveMethodTest.java	Tue Jul 15 19:21:28 2014 -0700
@@ -156,7 +156,7 @@
 
     }
 
-    private static ResolvedJavaMethod getMethod(ResolvedJavaType type, String methodName) {
+    static ResolvedJavaMethod getMethod(ResolvedJavaType type, String methodName) {
         for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
             if (method.getName().equals(methodName)) {
                 return method;
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,11 @@
 
 import static org.junit.Assert.*;
 
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.stream.*;
+
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
@@ -45,4 +50,91 @@
             assertEquals(expected, actual);
         }
     }
+
+    static class A {
+        A or(A other) {
+            return other;
+        }
+    }
+
+    @Test
+    public void testResolve() throws ClassNotFoundException {
+        String classPath = System.getProperty("java.class.path");
+        String[] parts = classPath.split(File.pathSeparator);
+        URL[] urls = Arrays.asList(parts).stream().map(e -> asURL(e)).collect(Collectors.toList()).toArray(new URL[parts.length]);
+        URLClassLoader clOne = newClassLoader(urls);
+        URLClassLoader clTwo = newClassLoader(urls);
+
+        String className = getClass().getName() + "$A";
+        Class<?> aClassOne = Class.forName(className, true, clOne);
+        Class<?> aClassTwo = Class.forName(getClass().getName() + "$A", true, clTwo);
+
+        assertNotEquals(aClassOne, aClassTwo);
+        assertNotEquals(aClassOne.getClassLoader(), aClassTwo.getClassLoader());
+
+        ResolvedJavaType aTypeOne = metaAccess.lookupJavaType(aClassOne);
+        ResolvedJavaType aTypeTwo = metaAccess.lookupJavaType(aClassTwo);
+
+        assertNotEquals(aTypeOne, aTypeTwo);
+
+        checkResolveWithoutAccessingClass(aTypeOne);
+        checkResolveWithoutAccessingClass(aTypeTwo);
+
+        assertEquals(aTypeOne.resolve(aTypeOne), aTypeOne);
+        assertNotEquals(aTypeOne.resolve(aTypeTwo), aTypeOne);
+        assertEquals(aTypeOne.resolve(aTypeTwo), aTypeTwo);
+
+        assertEquals(aTypeTwo.resolve(aTypeTwo), aTypeTwo);
+        assertNotEquals(aTypeTwo.resolve(aTypeOne), aTypeTwo);
+        assertEquals(aTypeTwo.resolve(aTypeOne), aTypeOne);
+
+        ResolvedJavaMethod m = ResolvedJavaTypeResolveMethodTest.getMethod(aTypeOne, "or");
+        JavaType resolvedTypeOne = m.getSignature().getParameterType(0, aTypeOne);
+        JavaType resolvedTypeTwo = m.getSignature().getReturnType(aTypeOne);
+        JavaType unresolvedTypeOne = m.getSignature().getParameterType(0, null);
+        JavaType unresolvedTypeTwo = m.getSignature().getReturnType(null);
+
+        assertTrue(resolvedTypeOne instanceof ResolvedJavaType);
+        assertTrue(resolvedTypeTwo instanceof ResolvedJavaType);
+        assertFalse(unresolvedTypeOne instanceof ResolvedJavaType);
+        assertFalse(unresolvedTypeTwo instanceof ResolvedJavaType);
+
+        assertEquals(resolvedTypeOne.resolve(aTypeOne), aTypeOne);
+        assertEquals(resolvedTypeOne.resolve(aTypeTwo), aTypeTwo);
+        assertEquals(resolvedTypeTwo.resolve(aTypeOne), aTypeOne);
+        assertEquals(resolvedTypeTwo.resolve(aTypeTwo), aTypeTwo);
+
+        checkResolveWithoutAccessingClass(unresolvedTypeOne);
+        checkResolveWithoutAccessingClass(unresolvedTypeTwo);
+
+        assertEquals(unresolvedTypeOne.resolve(aTypeOne), aTypeOne);
+        assertEquals(unresolvedTypeOne.resolve(aTypeTwo), aTypeTwo);
+    }
+
+    private static void checkResolveWithoutAccessingClass(JavaType type) {
+        try {
+            type.resolve(null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+    private static URLClassLoader newClassLoader(URL[] urls) {
+        URLClassLoader cl = new URLClassLoader(urls) {
+            @Override
+            protected java.lang.Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+                boolean callSuper = name.startsWith("java/") || name.startsWith("java.");
+                return callSuper ? super.loadClass(name, resolve) : super.findClass(name);
+            }
+        };
+        return cl;
+    }
+
+    private static URL asURL(String e) {
+        try {
+            return new File(e).toURI().toURL();
+        } catch (MalformedURLException e1) {
+            throw new RuntimeException(e1);
+        }
+    }
 }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java	Tue Jul 15 19:21:28 2014 -0700
@@ -44,7 +44,7 @@
             assertEquals(c.getModifiers(), type.getModifiers());
             if (!type.isArray()) {
                 assertEquals(type.getName(), toInternalName(c.getName()));
-                assertEquals(toJavaName(type), c.getName());
+                assertEquals(type.toJavaName(), c.getName());
             }
         }
     }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Tue Jul 15 19:21:28 2014 -0700
@@ -267,6 +267,18 @@
         assertTrue(2 <= method2StackSize && method2StackSize <= 4);
     }
 
+    @Test
+    public void isDefaultTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isDefault(), m.isDefault());
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertFalse(m.isDefault());
+        }
+    }
+
     private Method findTestMethod(Method apiMethod) {
         String testName = apiMethod.getName() + "Test";
         for (Method m : getClass().getDeclaredMethods()) {
@@ -291,7 +303,8 @@
         "getLineNumberTable",
         "getLocalVariableTable",
         "isInVirtualMethodTable",
-        "isDefault" // tested in TestResolvedJavaMethodJDK8
+        "toParameterTypes",
+        "getParameterAnnotation"
     };
     // @formatter:on
 
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Tue Jul 15 19:21:28 2014 -0700
@@ -709,7 +709,9 @@
         "getSourceFileName",
         "getClassFilePath",
         "isLocal",
+        "isJavaLangObject",
         "isMember",
+        "getElementalType",
         "getEnclosingType"
     };
     // @formatter:on
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java	Tue Jul 15 19:21:28 2014 -0700
@@ -93,7 +93,7 @@
 
     @Override
     public String toString() {
-        return "BaseProfilingInfo<" + MetaUtil.profileToString(this, null, "; ") + ">";
+        return "BaseProfilingInfo<" + this.toString(null, "; ") + ">";
     }
 
     public void setMature() {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaField.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaField.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.api.meta;
 
+import java.util.*;
+
 /**
  * Represents a reference to a Java field, either resolved or unresolved fields. Fields, like
  * methods and types, are resolved through {@link ConstantPool constant pools}.
@@ -49,4 +51,77 @@
      * field.
      */
     JavaType getDeclaringClass();
+
+    /**
+     * Gets a string for this field formatted according to a given format specification. A format
+     * specification is composed of characters that are to be copied verbatim to the result and
+     * specifiers that denote an attribute of this field that is to be copied to the result. A
+     * specifier is a single character preceded by a '%' character. The accepted specifiers and the
+     * field attributes they denote are described below:
+     *
+     * <pre>
+     *     Specifier | Description                                          | Example(s)
+     *     ----------+------------------------------------------------------------------------------------------
+     *     'T'       | Qualified type                                       | "int" "java.lang.String"
+     *     't'       | Unqualified type                                     | "int" "String"
+     *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
+     *     'h'       | Unqualified holder                                   | "Entry"
+     *     'n'       | Field name                                           | "age"
+     *     'f'       | Indicator if field is unresolved, static or instance | "unresolved" "static" "instance"
+     *     '%'       | A '%' character                                      | "%"
+     * </pre>
+     *
+     * @param format a format specification
+     * @return the result of formatting this field according to {@code format}
+     * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
+     */
+    default String format(String format) throws IllegalFormatException {
+        final StringBuilder sb = new StringBuilder();
+        int index = 0;
+        JavaType type = getType();
+        while (index < format.length()) {
+            final char ch = format.charAt(index++);
+            if (ch == '%') {
+                if (index >= format.length()) {
+                    throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a field format specification");
+                }
+                final char specifier = format.charAt(index++);
+                boolean qualified = false;
+                switch (specifier) {
+                    case 'T':
+                        qualified = true;
+                        // fall through
+                    case 't': {
+                        sb.append(type.toJavaName(qualified));
+                        break;
+                    }
+                    case 'H':
+                        qualified = true;
+                        // fall through
+                    case 'h': {
+                        sb.append(getDeclaringClass().toJavaName(qualified));
+                        break;
+                    }
+                    case 'n': {
+                        sb.append(getName());
+                        break;
+                    }
+                    case 'f': {
+                        sb.append(!(this instanceof ResolvedJavaField) ? "unresolved" : ((ResolvedJavaField) this).isStatic() ? "static" : "instance");
+                        break;
+                    }
+                    case '%': {
+                        sb.append('%');
+                        break;
+                    }
+                    default: {
+                        throw new UnknownFormatConversionException(String.valueOf(specifier));
+                    }
+                }
+            } else {
+                sb.append(ch);
+            }
+        }
+        return sb.toString();
+    }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaMethod.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaMethod.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.api.meta;
 
+import java.util.*;
+
 /**
  * Represents a reference to a Java method, either resolved or unresolved. Methods, like fields and
  * types, are resolved through {@link ConstantPool constant pools}.
@@ -43,4 +45,97 @@
      * Returns the signature of this method.
      */
     Signature getSignature();
+
+    /**
+     * Gets a string for this method formatted according to a given format specification. A format
+     * specification is composed of characters that are to be copied verbatim to the result and
+     * specifiers that denote an attribute of this method that is to be copied to the result. A
+     * specifier is a single character preceded by a '%' character. The accepted specifiers and the
+     * method attributes they denote are described below:
+     *
+     * <pre>
+     *     Specifier | Description                                          | Example(s)
+     *     ----------+------------------------------------------------------------------------------------------
+     *     'R'       | Qualified return type                                | "int" "java.lang.String"
+     *     'r'       | Unqualified return type                              | "int" "String"
+     *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
+     *     'h'       | Unqualified holder                                   | "Entry"
+     *     'n'       | Method name                                          | "add"
+     *     'P'       | Qualified parameter types, separated by ', '         | "int, java.lang.String"
+     *     'p'       | Unqualified parameter types, separated by ', '       | "int, String"
+     *     'f'       | Indicator if method is unresolved, static or virtual | "unresolved" "static" "virtual"
+     *     '%'       | A '%' character                                      | "%"
+     * </pre>
+     *
+     * @param format a format specification
+     * @return the result of formatting this method according to {@code format}
+     * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
+     */
+    default String format(String format) throws IllegalFormatException {
+        final StringBuilder sb = new StringBuilder();
+        int index = 0;
+        Signature sig = null;
+        while (index < format.length()) {
+            final char ch = format.charAt(index++);
+            if (ch == '%') {
+                if (index >= format.length()) {
+                    throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a method format specification");
+                }
+                final char specifier = format.charAt(index++);
+                boolean qualified = false;
+                switch (specifier) {
+                    case 'R':
+                        qualified = true;
+                        // fall through
+                    case 'r': {
+                        if (sig == null) {
+                            sig = getSignature();
+                        }
+                        sb.append(sig.getReturnType(null).toJavaName(qualified));
+                        break;
+                    }
+                    case 'H':
+                        qualified = true;
+                        // fall through
+                    case 'h': {
+                        sb.append(getDeclaringClass().toJavaName(qualified));
+                        break;
+                    }
+                    case 'n': {
+                        sb.append(getName());
+                        break;
+                    }
+                    case 'P':
+                        qualified = true;
+                        // fall through
+                    case 'p': {
+                        if (sig == null) {
+                            sig = getSignature();
+                        }
+                        for (int i = 0; i < sig.getParameterCount(false); i++) {
+                            if (i != 0) {
+                                sb.append(", ");
+                            }
+                            sb.append(sig.getParameterType(i, null).toJavaName(qualified));
+                        }
+                        break;
+                    }
+                    case 'f': {
+                        sb.append(!(this instanceof ResolvedJavaMethod) ? "unresolved" : ((ResolvedJavaMethod) this).isStatic() ? "static" : "virtual");
+                        break;
+                    }
+                    case '%': {
+                        sb.append('%');
+                        break;
+                    }
+                    default: {
+                        throw new UnknownFormatConversionException(String.valueOf(specifier));
+                    }
+                }
+            } else {
+                sb.append(ch);
+            }
+        }
+        return sb.toString();
+    }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.api.meta;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
 /**
  * Represents a resolved or unresolved type. Types include primitives, objects, {@code void}, and
  * arrays thereof.
@@ -31,7 +33,7 @@
     /**
      * Returns the name of this type in internal form. The following are examples of strings
      * returned by this method:
-     * 
+     *
      * <pre>
      *     "Ljava/lang/Object;"
      *     "I"
@@ -47,6 +49,19 @@
     JavaType getComponentType();
 
     /**
+     * Gets the elemental type for this given type. The elemental type is the corresponding zero
+     * dimensional type of an array type. For example, the elemental type of {@code int[][][]} is
+     * {@code int}. A non-array type is its own elemental type.
+     */
+    default JavaType getElementalType() {
+        JavaType t = this;
+        while (t.getComponentType() != null) {
+            t = t.getComponentType();
+        }
+        return t;
+    }
+
+    /**
      * Gets the array class type representing an array with elements of this type.
      */
     JavaType getArrayClass();
@@ -57,11 +72,63 @@
     Kind getKind();
 
     /**
-     * Resolved this type and returns a {@link ResolvedJavaType}. If this type is already a
-     * {@link ResolvedJavaType}, it returns this type.
-     * 
-     * @param accessingClass the class that requests resolving this type
+     * Resolves this type to a {@link ResolvedJavaType}.
+     *
+     * @param accessingClass the context of resolution (must not be null)
      * @return the resolved Java type
+     * @throws LinkageError if the resolution failed
+     * @throws NullPointerException if {@code accessingClass} is {@code null}
      */
     ResolvedJavaType resolve(ResolvedJavaType accessingClass);
+
+    /**
+     * Gets the Java programming language name for this type. The following are examples of strings
+     * returned by this method:
+     *
+     * <pre>
+     *      java.lang.Object
+     *      int
+     *      boolean[][]
+     * </pre>
+     *
+     * @return the Java name corresponding to this type
+     */
+    default String toJavaName() {
+        return internalNameToJava(getName(), true, false);
+    }
+
+    /**
+     * Gets the Java programming language name for this type. The following are examples of strings
+     * returned by this method:
+     *
+     * <pre>
+     *     qualified == true:
+     *         java.lang.Object
+     *         int
+     *         boolean[][]
+     *     qualified == false:
+     *         Object
+     *         int
+     *         boolean[][]
+     * </pre>
+     *
+     * @param qualified specifies if the package prefix of this type should be included in the
+     *            returned name
+     * @return the Java name corresponding to this type
+     */
+    default String toJavaName(boolean qualified) {
+        Kind kind = getKind();
+        if (kind == Kind.Object) {
+            return internalNameToJava(getName(), qualified, false);
+        }
+        return getKind().getJavaName();
+    }
+
+    /**
+     * Returns this type's name in the same format as {@link Class#getName()}.
+     */
+    default String toClassName() {
+        return internalNameToJava(getName(), true, true);
+    }
+
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Tue Jul 15 19:21:28 2014 -0700
@@ -305,7 +305,7 @@
                         return "String:\"" + s + '"';
                     }
                 } else if (value instanceof JavaType) {
-                    return "JavaType:" + MetaUtil.toJavaName((JavaType) value);
+                    return "JavaType:" + ((JavaType) value).toJavaName();
                 } else if (value instanceof Enum) {
                     return MetaUtil.getSimpleName(value.getClass(), true) + ":" + ((Enum<?>) value).name();
                 } else if (value instanceof FormatWithToString) {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Tue Jul 15 19:21:28 2014 -0700
@@ -31,13 +31,27 @@
 
     /**
      * Returns the resolved Java type representing a given Java class.
-     * 
+     *
      * @param clazz the Java class object
      * @return the resolved Java type object
      */
     ResolvedJavaType lookupJavaType(Class<?> clazz);
 
     /**
+     * Returns the resolved Java types representing some given Java classes.
+     *
+     * @param classes the Java class objects
+     * @return the resolved Java type objects
+     */
+    default ResolvedJavaType[] lookupJavaTypes(Class<?>[] classes) {
+        ResolvedJavaType[] result = new ResolvedJavaType[classes.length];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = lookupJavaType(classes[i]);
+        }
+        return result;
+    }
+
+    /**
      * Provides the {@link ResolvedJavaMethod} for a {@link Method} obtained via reflection.
      */
     ResolvedJavaMethod lookupJavaMethod(Method reflectionMethod);
@@ -54,14 +68,14 @@
 
     /**
      * Returns the resolved Java type of the given {@link Constant} object.
-     * 
+     *
      * @return {@code null} if {@code constant.isNull() || !constant.kind.isObject()}
      */
     ResolvedJavaType lookupJavaType(Constant constant);
 
     /**
      * Returns the number of bytes occupied by this constant value or constant object.
-     * 
+     *
      * @param constant the constant whose bytes should be measured
      * @return the number of bytes occupied by this constant
      */
@@ -77,11 +91,11 @@
 
     /**
      * Encodes a deoptimization action and a deoptimization reason in an integer value.
-     * 
+     *
      * @param debugId an integer that can be used to track the origin of a deoptimization at
      *            runtime. There is no guarantee that the runtime will use this value. The runtime
      *            may even keep fewer than 32 bits.
-     * 
+     *
      * @return the encoded value as an integer
      */
     Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId);
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,11 +24,8 @@
 
 import java.io.*;
 import java.lang.annotation.*;
-import java.lang.reflect.*;
 import java.util.*;
 
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
-
 /**
  * Miscellaneous collection of utility methods used by {@code com.oracle.graal.api.meta} and its
  * clients.
@@ -134,15 +131,6 @@
     }
 
     /**
-     * Returns true if the specified typed is exactly the type {@link java.lang.Object}.
-     */
-    public static boolean isJavaLangObject(ResolvedJavaType type) {
-        boolean result = type.getSuperclass() == null && !type.isInterface() && type.getKind() == Kind.Object;
-        assert result == type.getName().equals("Ljava/lang/Object;") : type.getName();
-        return result;
-    }
-
-    /**
      * Calls {@link JavaType#resolve(ResolvedJavaType)} on an array of types.
      */
     public static ResolvedJavaType[] resolveJavaTypes(JavaType[] types, ResolvedJavaType accessingClass) {
@@ -154,30 +142,6 @@
     }
 
     /**
-     * Calls {@link MetaAccessProvider#lookupJavaType(Class)} on an array of classes.
-     */
-    public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class<?>[] classes) {
-        ResolvedJavaType[] result = new ResolvedJavaType[classes.length];
-        for (int i = 0; i < result.length; i++) {
-            result[i] = metaAccess.lookupJavaType(classes[i]);
-        }
-        return result;
-    }
-
-    /**
-     * Gets the elemental type for a given type. The elemental type of an array type is the
-     * corresponding zero dimensional (e.g., the elemental type of {@code int[][][]} is {@code int}
-     * ). A non-array type is its own elemental type.
-     */
-    public static ResolvedJavaType getElementalType(ResolvedJavaType type) {
-        ResolvedJavaType t = type;
-        while (t.getComponentType() != null) {
-            t = t.getComponentType();
-        }
-        return t;
-    }
-
-    /**
      * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for
      * anonymous and local classes.
      *
@@ -213,59 +177,7 @@
         return name.substring(index + 1);
     }
 
-    /**
-     * Converts a given type to its Java programming language name. The following are examples of
-     * strings returned by this method:
-     *
-     * <pre>
-     *     qualified == true:
-     *         java.lang.Object
-     *         int
-     *         boolean[][]
-     *     qualified == false:
-     *         Object
-     *         int
-     *         boolean[][]
-     * </pre>
-     *
-     * @param type the type to be converted to a Java name
-     * @param qualified specifies if the package prefix of the type should be included in the
-     *            returned name
-     * @return the Java name corresponding to {@code type}
-     */
-    public static String toJavaName(JavaType type, boolean qualified) {
-        Kind kind = type.getKind();
-        if (kind == Kind.Object) {
-            return internalNameToJava(type.getName(), qualified, false);
-        }
-        return type.getKind().getJavaName();
-    }
-
-    /**
-     * Converts a given type to its Java programming language name. The following are examples of
-     * strings returned by this method:
-     *
-     * <pre>
-     *      java.lang.Object
-     *      int
-     *      boolean[][]
-     * </pre>
-     *
-     * @param type the type to be converted to a Java name
-     * @return the Java name corresponding to {@code type}
-     */
-    public static String toJavaName(JavaType type) {
-        return (type == null) ? null : internalNameToJava(type.getName(), true, false);
-    }
-
-    /**
-     * Returns the type name in the same format as {@link Class#getName()}.
-     */
-    public static String toClassName(JavaType type) {
-        return internalNameToJava(type.getName(), true, true);
-    }
-
-    private static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) {
+    static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) {
         switch (name.charAt(0)) {
             case 'L': {
                 String result = name.substring(1, name.length() - 1).replace('/', '.');
@@ -301,221 +213,8 @@
     }
 
     /**
-     * Gets a string for a given method formatted according to a given format specification. A
-     * format specification is composed of characters that are to be copied verbatim to the result
-     * and specifiers that denote an attribute of the method that is to be copied to the result. A
-     * specifier is a single character preceded by a '%' character. The accepted specifiers and the
-     * method attributes they denote are described below:
-     *
-     * <pre>
-     *     Specifier | Description                                          | Example(s)
-     *     ----------+------------------------------------------------------------------------------------------
-     *     'R'       | Qualified return type                                | "int" "java.lang.String"
-     *     'r'       | Unqualified return type                              | "int" "String"
-     *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
-     *     'h'       | Unqualified holder                                   | "Entry"
-     *     'n'       | Method name                                          | "add"
-     *     'P'       | Qualified parameter types, separated by ', '         | "int, java.lang.String"
-     *     'p'       | Unqualified parameter types, separated by ', '       | "int, String"
-     *     'f'       | Indicator if method is unresolved, static or virtual | "unresolved" "static" "virtual"
-     *     '%'       | A '%' character                                      | "%"
-     * </pre>
-     *
-     * @param format a format specification
-     * @param method the method to be formatted
-     * @return the result of formatting this method according to {@code format}
-     * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
-     */
-    public static String format(String format, JavaMethod method) throws IllegalFormatException {
-        final StringBuilder sb = new StringBuilder();
-        int index = 0;
-        Signature sig = null;
-        while (index < format.length()) {
-            final char ch = format.charAt(index++);
-            if (ch == '%') {
-                if (index >= format.length()) {
-                    throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a method format specification");
-                }
-                final char specifier = format.charAt(index++);
-                boolean qualified = false;
-                switch (specifier) {
-                    case 'R':
-                        qualified = true;
-                        // fall through
-                    case 'r': {
-                        if (sig == null) {
-                            sig = method.getSignature();
-                        }
-                        sb.append(toJavaName(sig.getReturnType(null), qualified));
-                        break;
-                    }
-                    case 'H':
-                        qualified = true;
-                        // fall through
-                    case 'h': {
-                        sb.append(toJavaName(method.getDeclaringClass(), qualified));
-                        break;
-                    }
-                    case 'n': {
-                        sb.append(method.getName());
-                        break;
-                    }
-                    case 'P':
-                        qualified = true;
-                        // fall through
-                    case 'p': {
-                        if (sig == null) {
-                            sig = method.getSignature();
-                        }
-                        for (int i = 0; i < sig.getParameterCount(false); i++) {
-                            if (i != 0) {
-                                sb.append(", ");
-                            }
-                            sb.append(toJavaName(sig.getParameterType(i, null), qualified));
-                        }
-                        break;
-                    }
-                    case 'f': {
-                        sb.append(!(method instanceof ResolvedJavaMethod) ? "unresolved" : ((ResolvedJavaMethod) method).isStatic() ? "static" : "virtual");
-                        break;
-                    }
-                    case '%': {
-                        sb.append('%');
-                        break;
-                    }
-                    default: {
-                        throw new UnknownFormatConversionException(String.valueOf(specifier));
-                    }
-                }
-            } else {
-                sb.append(ch);
-            }
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Gets a string for a given field formatted according to a given format specification. A format
-     * specification is composed of characters that are to be copied verbatim to the result and
-     * specifiers that denote an attribute of the field that is to be copied to the result. A
-     * specifier is a single character preceded by a '%' character. The accepted specifiers and the
-     * field attributes they denote are described below:
-     *
-     * <pre>
-     *     Specifier | Description                                          | Example(s)
-     *     ----------+------------------------------------------------------------------------------------------
-     *     'T'       | Qualified type                                       | "int" "java.lang.String"
-     *     't'       | Unqualified type                                     | "int" "String"
-     *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
-     *     'h'       | Unqualified holder                                   | "Entry"
-     *     'n'       | Field name                                           | "age"
-     *     'f'       | Indicator if field is unresolved, static or instance | "unresolved" "static" "instance"
-     *     '%'       | A '%' character                                      | "%"
-     * </pre>
-     *
-     * @param format a format specification
-     * @param field the field to be formatted
-     * @return the result of formatting this field according to {@code format}
-     * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
-     */
-    public static String format(String format, JavaField field) throws IllegalFormatException {
-        final StringBuilder sb = new StringBuilder();
-        int index = 0;
-        JavaType type = field.getType();
-        while (index < format.length()) {
-            final char ch = format.charAt(index++);
-            if (ch == '%') {
-                if (index >= format.length()) {
-                    throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a field format specification");
-                }
-                final char specifier = format.charAt(index++);
-                boolean qualified = false;
-                switch (specifier) {
-                    case 'T':
-                        qualified = true;
-                        // fall through
-                    case 't': {
-                        sb.append(toJavaName(type, qualified));
-                        break;
-                    }
-                    case 'H':
-                        qualified = true;
-                        // fall through
-                    case 'h': {
-                        sb.append(toJavaName(field.getDeclaringClass(), qualified));
-                        break;
-                    }
-                    case 'n': {
-                        sb.append(field.getName());
-                        break;
-                    }
-                    case 'f': {
-                        sb.append(!(field instanceof ResolvedJavaField) ? "unresolved" : ((ResolvedJavaField) field).isStatic() ? "static" : "instance");
-                        break;
-                    }
-                    case '%': {
-                        sb.append('%');
-                        break;
-                    }
-                    default: {
-                        throw new UnknownFormatConversionException(String.valueOf(specifier));
-                    }
-                }
-            } else {
-                sb.append(ch);
-            }
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Gets the annotations of a particular type for the formal parameters of a given method.
-     *
-     * @param annotationClass the Class object corresponding to the annotation type
-     * @param method the method for which a parameter annotations are being requested
-     * @return the annotation of type {@code annotationClass} (if any) for each formal parameter
-     *         present
-     */
-    @SuppressWarnings("unchecked")
-    public static <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationClass, ResolvedJavaMethod method) {
-        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
-        T[] result = (T[]) Array.newInstance(annotationClass, parameterAnnotations.length);
-        for (int i = 0; i < parameterAnnotations.length; i++) {
-            for (Annotation a : parameterAnnotations[i]) {
-                if (a.annotationType() == annotationClass) {
-                    result[i] = annotationClass.cast(a);
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Gets the annotation of a particular type for a formal parameter of a given method.
-     *
-     * @param annotationClass the Class object corresponding to the annotation type
-     * @param parameterIndex the index of a formal parameter of {@code method}
-     * @param method the method for which a parameter annotation is being requested
-     * @return the annotation of type {@code annotationClass} for the formal parameter present, else
-     *         null
-     * @throws IndexOutOfBoundsException if {@code parameterIndex} does not denote a formal
-     *             parameter
-     */
-    public static <T extends Annotation> T getParameterAnnotation(Class<T> annotationClass, int parameterIndex, ResolvedJavaMethod method) {
-        if (parameterIndex >= 0) {
-            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
-            for (Annotation a : parameterAnnotations[parameterIndex]) {
-                if (a.annotationType() == annotationClass) {
-                    return annotationClass.cast(a);
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
      * Convenient shortcut for calling
-     * {@link #appendLocation(StringBuilder, ResolvedJavaMethod, int)} without having to supply a a
+     * {@link #appendLocation(StringBuilder, ResolvedJavaMethod, int)} without having to supply a
      * {@link StringBuilder} instance and convert the result to a string.
      */
     public static String toLocation(ResolvedJavaMethod method, int bci) {
@@ -533,7 +232,7 @@
      *     java.lang.String.valueOf(String.java:2930) [bci: 12]
      * </pre>
      *
-     * Otherwise, the string returned is the value of applying {@link #format(String, JavaMethod)}
+     * Otherwise, the string returned is the value of applying {@link JavaMethod#format(String)}
      * with the format string {@code "%H.%n(%p)"}, suffixed by the bci location. For example:
      *
      * <pre>
@@ -550,7 +249,7 @@
             if (ste.getFileName() != null && ste.getLineNumber() > 0) {
                 sb.append(ste);
             } else {
-                sb.append(format("%H.%n(%p)", method));
+                sb.append(method.format("%H.%n(%p)"));
             }
         } else {
             sb.append("Null method");
@@ -558,116 +257,7 @@
         return sb.append(" [bci: ").append(bci).append(']');
     }
 
-    public static JavaType[] signatureToTypes(ResolvedJavaMethod method) {
-        JavaType receiver = method.isStatic() ? null : method.getDeclaringClass();
-        return signatureToTypes(method.getSignature(), receiver);
-    }
-
-    public static JavaType[] signatureToTypes(Signature signature, JavaType receiverType) {
-        int args = signature.getParameterCount(false);
-        JavaType[] result;
-        int i = 0;
-        if (receiverType != null) {
-            result = new JavaType[args + 1];
-            result[0] = receiverType;
-            i = 1;
-        } else {
-            result = new JavaType[args];
-        }
-        for (int j = 0; j < args; j++) {
-            result[i + j] = signature.getParameterType(j, null);
-        }
-        return result;
-    }
-
-    /**
-     * Gets the <a
-     * href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method
-     * descriptor</a> corresponding to this signature. For example:
-     *
-     * <pre>
-     * (ILjava/lang/String;D)V
-     * </pre>
-     *
-     * .
-     *
-     * @param sig the {@link Signature} to be converted.
-     * @return the signature as a string
-     */
-    public static String signatureToMethodDescriptor(Signature sig) {
-        StringBuilder sb = new StringBuilder("(");
-        for (int i = 0; i < sig.getParameterCount(false); ++i) {
-            sb.append(sig.getParameterType(i, null).getName());
-        }
-        sb.append(')').append(sig.getReturnType(null).getName());
-        return sb.toString();
-    }
-
-    /**
-     * Formats some profiling information associated as a string.
-     *
-     * @param info the profiling info to format
-     * @param method an optional method that augments the profile string returned
-     * @param sep the separator to use for each separate profile record
-     */
-    public static String profileToString(ProfilingInfo info, ResolvedJavaMethod method, String sep) {
-        StringBuilder buf = new StringBuilder(100);
-        if (method != null) {
-            buf.append(String.format("canBeStaticallyBound: %b%s", method.canBeStaticallyBound(), sep));
-        }
-        for (int i = 0; i < info.getCodeSize(); i++) {
-            if (info.getExecutionCount(i) != -1) {
-                buf.append(String.format("executionCount@%d: %d%s", i, info.getExecutionCount(i), sep));
-            }
-
-            if (info.getBranchTakenProbability(i) != -1) {
-                buf.append(String.format("branchProbability@%d: %.6f%s", i, info.getBranchTakenProbability(i), sep));
-            }
-
-            double[] switchProbabilities = info.getSwitchProbabilities(i);
-            if (switchProbabilities != null) {
-                buf.append(String.format("switchProbabilities@%d:", i));
-                for (int j = 0; j < switchProbabilities.length; j++) {
-                    buf.append(String.format(" %.6f", switchProbabilities[j]));
-                }
-                buf.append(sep);
-            }
-
-            if (info.getExceptionSeen(i) != TriState.UNKNOWN) {
-                buf.append(String.format("exceptionSeen@%d: %s%s", i, info.getExceptionSeen(i).name(), sep));
-            }
-
-            if (info.getNullSeen(i) != TriState.UNKNOWN) {
-                buf.append(String.format("nullSeen@%d: %s%s", i, info.getNullSeen(i).name(), sep));
-            }
-
-            JavaTypeProfile typeProfile = info.getTypeProfile(i);
-            appendProfile(buf, typeProfile, i, "types", sep);
-
-            JavaMethodProfile methodProfile = info.getMethodProfile(i);
-            appendProfile(buf, methodProfile, i, "methods", sep);
-        }
-
-        boolean firstDeoptReason = true;
-        for (DeoptimizationReason reason : DeoptimizationReason.values()) {
-            int count = info.getDeoptimizationCount(reason);
-            if (count > 0) {
-                if (firstDeoptReason) {
-                    buf.append("deoptimization history").append(sep);
-                    firstDeoptReason = false;
-                }
-                buf.append(String.format(" %s: %d%s", reason.name(), count, sep));
-            }
-        }
-        if (buf.length() == 0) {
-            return "";
-        }
-        String s = buf.toString();
-        assert s.endsWith(sep);
-        return s.substring(0, s.length() - sep.length());
-    }
-
-    private static void appendProfile(StringBuilder buf, AbstractJavaProfile<?, ?> profile, int bci, String type, String sep) {
+    static void appendProfile(StringBuilder buf, AbstractJavaProfile<?, ?> profile, int bci, String type, String sep) {
         if (profile != null) {
             AbstractProfiledItem<?>[] pitems = profile.getItems();
             if (pitems != null) {
@@ -743,4 +333,78 @@
         }
         return indentation + lines.replace(newLine, newLine + indentation);
     }
+
+    // The methods below here will be soon removed. They exist to simplify updating
+    // clients of the old API to switch to using the default methods that replace
+    // these utility methods. In Eclipse will show calls to these methods as warnings.
+
+    @Deprecated
+    public static boolean isJavaLangObject(ResolvedJavaType type) {
+        return type.isJavaLangObject();
+    }
+
+    @Deprecated
+    public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class<?>[] classes) {
+        return metaAccess.lookupJavaTypes(classes);
+    }
+
+    @Deprecated
+    public static ResolvedJavaType getElementalType(ResolvedJavaType type) {
+        return type.getElementalType();
+    }
+
+    @Deprecated
+    public static String toJavaName(JavaType type, boolean qualified) {
+        return type.toJavaName(qualified);
+    }
+
+    @Deprecated
+    public static String toJavaName(JavaType type) {
+        return type.toJavaName();
+    }
+
+    @Deprecated
+    public static String toClassName(JavaType type) {
+        return type.toClassName();
+    }
+
+    @Deprecated
+    public static String format(String format, JavaMethod method) throws IllegalFormatException {
+        return method.format(format);
+    }
+
+    @Deprecated
+    public static String format(String format, JavaField field) throws IllegalFormatException {
+        return field.format(format);
+    }
+
+    @Deprecated
+    public static <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationClass, ResolvedJavaMethod method) {
+        return method.getParameterAnnotations(annotationClass);
+    }
+
+    @Deprecated
+    public static <T extends Annotation> T getParameterAnnotation(Class<T> annotationClass, int parameterIndex, ResolvedJavaMethod method) {
+        return method.getParameterAnnotation(annotationClass, parameterIndex);
+    }
+
+    @Deprecated
+    public static JavaType[] signatureToTypes(Signature signature, JavaType receiverType) {
+        return signature.toParameterTypes(receiverType);
+    }
+
+    @Deprecated
+    public static JavaType[] signatureToTypes(ResolvedJavaMethod method) {
+        return method.toParameterTypes();
+    }
+
+    @Deprecated
+    public static String signatureToMethodDescriptor(Signature sig) {
+        return sig.toMethodDescriptor();
+    }
+
+    @Deprecated
+    public static String profileToString(ProfilingInfo info, ResolvedJavaMethod method, String sep) {
+        return info.toString(method, sep);
+    }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Tue Jul 15 19:21:28 2014 -0700
@@ -50,7 +50,7 @@
 
     /**
      * Returns an estimate of how often the branch at the given byte code was taken.
-     * 
+     *
      * @return The estimated probability, with 0.0 meaning never and 1.0 meaning always, or -1 if
      *         this information is not available.
      */
@@ -59,7 +59,7 @@
     /**
      * Returns an estimate of how often the switch cases are taken at the given BCI. The default
      * case is stored as the last entry.
-     * 
+     *
      * @return A double value that contains the estimated probabilities, with 0.0 meaning never and
      *         1.0 meaning always, or -1 if this information is not available.
      */
@@ -67,21 +67,21 @@
 
     /**
      * Returns the TypeProfile for the given BCI.
-     * 
+     *
      * @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.
@@ -91,7 +91,7 @@
     /**
      * Returns information if null was ever seen for the given BCI. This information is collected
      * for the aastore, checkcast and instanceof bytecodes.
-     * 
+     *
      * @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.
      */
@@ -100,7 +100,7 @@
     /**
      * Returns an estimate how often the current BCI was executed. Avoid comparing execution counts
      * to each other, as the returned value highly depends on the time of invocation.
-     * 
+     *
      * @return the estimated execution count or -1 if not available.
      */
     int getExecutionCount(int bci);
@@ -109,7 +109,7 @@
      * Returns how frequently a method was deoptimized for the given deoptimization reason. This
      * only indicates how often the method did fall back to the interpreter for the execution and
      * does not indicate how often it was recompiled.
-     * 
+     *
      * @param reason the reason for which the number of deoptimizations should be queried
      * @return the number of times the compiled method deoptimized for the given reason.
      */
@@ -118,7 +118,7 @@
     /**
      * Records the size of the compiler intermediate representation (IR) associated with this
      * method.
-     * 
+     *
      * @param irType the IR type for which the size is being recorded
      * @param irSize the IR size to be recorded. The unit depends on the IR.
      * @return whether recording this information for {@code irType} is supported
@@ -128,7 +128,7 @@
     /**
      * Gets the size of the compiler intermediate representation (IR) associated with this method
      * last recorded by {@link #setCompilerIRSize(Class, int)}.
-     * 
+     *
      * @param irType the IR type for which the size is being requested
      * @return the requested IR size or -1 if it is unavailable for {@code irType}
      */
@@ -136,7 +136,7 @@
 
     /**
      * Returns true if the profiling information can be assumed as sufficiently accurate.
-     * 
+     *
      * @return true if the profiling information was recorded often enough mature enough, false
      *         otherwise.
      */
@@ -146,4 +146,67 @@
      * Force data to be treated as mature if possible.
      */
     void setMature();
+
+    /**
+     * Formats this profiling information to a string.
+     *
+     * @param method an optional method that augments the profile string returned
+     * @param sep the separator to use for each separate profile record
+     */
+    default String toString(ResolvedJavaMethod method, String sep) {
+        StringBuilder buf = new StringBuilder(100);
+        if (method != null) {
+            buf.append(String.format("canBeStaticallyBound: %b%s", method.canBeStaticallyBound(), sep));
+        }
+        for (int i = 0; i < getCodeSize(); i++) {
+            if (getExecutionCount(i) != -1) {
+                buf.append(String.format("executionCount@%d: %d%s", i, getExecutionCount(i), sep));
+            }
+
+            if (getBranchTakenProbability(i) != -1) {
+                buf.append(String.format("branchProbability@%d: %.6f%s", i, getBranchTakenProbability(i), sep));
+            }
+
+            double[] switchProbabilities = getSwitchProbabilities(i);
+            if (switchProbabilities != null) {
+                buf.append(String.format("switchProbabilities@%d:", i));
+                for (int j = 0; j < switchProbabilities.length; j++) {
+                    buf.append(String.format(" %.6f", switchProbabilities[j]));
+                }
+                buf.append(sep);
+            }
+
+            if (getExceptionSeen(i) != TriState.UNKNOWN) {
+                buf.append(String.format("exceptionSeen@%d: %s%s", i, getExceptionSeen(i).name(), sep));
+            }
+
+            if (getNullSeen(i) != TriState.UNKNOWN) {
+                buf.append(String.format("nullSeen@%d: %s%s", i, getNullSeen(i).name(), sep));
+            }
+
+            JavaTypeProfile typeProfile = getTypeProfile(i);
+            MetaUtil.appendProfile(buf, typeProfile, i, "types", sep);
+
+            JavaMethodProfile methodProfile = getMethodProfile(i);
+            MetaUtil.appendProfile(buf, methodProfile, i, "methods", sep);
+        }
+
+        boolean firstDeoptReason = true;
+        for (DeoptimizationReason reason : DeoptimizationReason.values()) {
+            int count = getDeoptimizationCount(reason);
+            if (count > 0) {
+                if (firstDeoptReason) {
+                    buf.append("deoptimization history").append(sep);
+                    firstDeoptReason = false;
+                }
+                buf.append(String.format(" %s: %d%s", reason.name(), count, sep));
+            }
+        }
+        if (buf.length() == 0) {
+            return "";
+        }
+        String s = buf.toString();
+        return s.substring(0, s.length() - sep.length());
+    }
+
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Tue Jul 15 19:21:28 2014 -0700
@@ -224,4 +224,53 @@
      * @return true is this method is present in the virtual table for subtypes of this type.
      */
     boolean isInVirtualMethodTable(ResolvedJavaType resolved);
+
+    /**
+     * Gets the annotation of a particular type for a formal parameter of this method.
+     *
+     * @param annotationClass the Class object corresponding to the annotation type
+     * @param parameterIndex the index of a formal parameter of {@code method}
+     * @return the annotation of type {@code annotationClass} for the formal parameter present, else
+     *         null
+     * @throws IndexOutOfBoundsException if {@code parameterIndex} does not denote a formal
+     *             parameter
+     */
+    default <T extends Annotation> T getParameterAnnotation(Class<T> annotationClass, int parameterIndex) {
+        if (parameterIndex >= 0) {
+            Annotation[][] parameterAnnotations = getParameterAnnotations();
+            for (Annotation a : parameterAnnotations[parameterIndex]) {
+                if (a.annotationType() == annotationClass) {
+                    return annotationClass.cast(a);
+                }
+            }
+        }
+        return null;
+    }
+
+    default JavaType[] toParameterTypes() {
+        JavaType receiver = isStatic() ? null : getDeclaringClass();
+        return getSignature().toParameterTypes(receiver);
+    }
+
+    /**
+     * Gets the annotations of a particular type for the formal parameters of this method.
+     *
+     * @param annotationClass the Class object corresponding to the annotation type
+     * @return the annotation of type {@code annotationClass} (if any) for each formal parameter
+     *         present
+     */
+    @SuppressWarnings("unchecked")
+    default <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationClass) {
+        Annotation[][] parameterAnnotations = getParameterAnnotations();
+        T[] result = (T[]) Array.newInstance(annotationClass, parameterAnnotations.length);
+        for (int i = 0; i < parameterAnnotations.length; i++) {
+            for (Annotation a : parameterAnnotations[i]) {
+                if (a.annotationType() == annotationClass) {
+                    result[i] = annotationClass.cast(a);
+                }
+            }
+        }
+        return result;
+    }
+
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Tue Jul 15 19:21:28 2014 -0700
@@ -141,6 +141,14 @@
     boolean isAssignableFrom(ResolvedJavaType other);
 
     /**
+     * Returns true if this type is exactly the type {@link java.lang.Object}.
+     */
+    default boolean isJavaLangObject() {
+        // Removed assertion due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=434442
+        return getSuperclass() == null && !isInterface() && getKind() == Kind.Object;
+    }
+
+    /**
      * Checks whether the specified object is an instance of this type.
      *
      * @param obj the object to test
@@ -183,8 +191,8 @@
      * Attempts to get a unique concrete subclass of this type.
      * <p>
      * For an {@linkplain #isArray() array} type A, the unique concrete subclass is A if the
-     * {@linkplain MetaUtil#getElementalType(ResolvedJavaType) elemental} type of A is final (which
-     * includes primitive types). Otherwise {@code null} is returned for A.
+     * {@linkplain #getElementalType() elemental} type of A is final (which includes primitive
+     * types). Otherwise {@code null} is returned for A.
      * <p>
      * For a non-array type T, the result is the unique concrete type in the current hierarchy of T.
      * <p>
@@ -202,6 +210,14 @@
 
     ResolvedJavaType getComponentType();
 
+    default ResolvedJavaType getElementalType() {
+        ResolvedJavaType t = this;
+        while (t.isArray()) {
+            t = t.getComponentType();
+        }
+        return t;
+    }
+
     ResolvedJavaType getArrayClass();
 
     /**
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Signature.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Signature.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,7 +24,7 @@
 
 /**
  * Represents a method signature provided by the runtime.
- * 
+ *
  * @see <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">Method
  *      Descriptors</a>
  */
@@ -32,43 +32,44 @@
 
     /**
      * Returns the number of parameters in this signature, adding 1 for a receiver if requested.
-     * 
+     *
      * @param receiver true if 1 is to be added to the result for a receiver
      * @return the number of parameters; + 1 iff {@code receiver == true}
      */
     int getParameterCount(boolean receiver);
 
     /**
-     * Gets the parameter type at the specified position. This method returns a
-     * {@linkplain ResolvedJavaType resolved} type if possible but without triggering any class
-     * loading or resolution.
-     * 
+     * Gets the parameter type at the specified position.
+     *
      * @param index the index into the parameters, with {@code 0} indicating the first parameter
-     * @param accessingClass the context of the type lookup. If accessing class is provided, its
-     *            class loader is used to retrieve an existing resolved type. This value can be
-     *            {@code null} if the caller does not care for a resolved type.
+     * @param accessingClass the context of the type lookup. If non-null, its class loader is used
+     *            for resolving the type. If {@code null}, then the type returned is either
+     *            unresolved or a resolved type whose resolution is context free (e.g., a primitive
+     *            type or a type in a java.* package).
      * @return the {@code index}'th parameter type
+     * @throws LinkageError if {@code accessingClass != null} and resolution fails
+     *
      */
     JavaType getParameterType(int index, ResolvedJavaType accessingClass);
 
     /**
      * Gets the parameter kind at the specified position. This is the same as calling
      * {@link #getParameterType}. {@link JavaType#getKind getKind}.
-     * 
+     *
      * @param index the index into the parameters, with {@code 0} indicating the first parameter
      * @return the kind of the parameter at the specified position
      */
     Kind getParameterKind(int index);
 
     /**
-     * Gets the return type of this signature. This method will return a
-     * {@linkplain ResolvedJavaType resolved} type if possible but without triggering any class
-     * loading or resolution.
-     * 
-     * @param accessingClass the context of the type lookup. If accessing class is provided, its
-     *            class loader is used to retrieve an existing resolved type. This value can be
-     *            {@code null} if the caller does not care for a resolved type.
+     * Gets the return type of this signature.
+     *
+     * @param accessingClass the context of the type lookup. If non-null, its class loader is used
+     *            for resolving the type. If {@code null}, then the type returned is either
+     *            unresolved or a resolved type whose resolution is context free (e.g., a primitive
+     *            type or a type in a java.* package).
      * @return the return type
+     * @throws LinkageError if {@code accessingClass != null} and resolution fails
      */
     JavaType getReturnType(ResolvedJavaType accessingClass);
 
@@ -80,10 +81,47 @@
 
     /**
      * Gets the size, in Java slots, of the parameters to this signature.
-     * 
+     *
      * @param withReceiver {@code true} if to add a slot for a receiver object; {@code false} not to
      *            include the receiver
      * @return the size of the parameters in slots
      */
     int getParameterSlots(boolean withReceiver);
+
+    /**
+     * Gets the <a
+     * href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method
+     * descriptor</a> corresponding to this signature. For example:
+     *
+     * <pre>
+     * (ILjava/lang/String;D)V
+     * </pre>
+     *
+     * @return the signature as a string
+     */
+    default String toMethodDescriptor() {
+        StringBuilder sb = new StringBuilder("(");
+        for (int i = 0; i < getParameterCount(false); ++i) {
+            sb.append(getParameterType(i, null).getName());
+        }
+        sb.append(')').append(getReturnType(null).getName());
+        return sb.toString();
+    }
+
+    default JavaType[] toParameterTypes(JavaType receiverType) {
+        int args = getParameterCount(false);
+        JavaType[] result;
+        int i = 0;
+        if (receiverType != null) {
+            result = new JavaType[args + 1];
+            result[0] = receiverType;
+            i = 1;
+        } else {
+            result = new JavaType[args];
+        }
+        for (int j = 0; j < args; j++) {
+            result[i + j] = getParameterType(j, null);
+        }
+        return result;
+    }
 }
--- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java	Tue Jul 15 19:21:28 2014 -0700
@@ -48,7 +48,7 @@
     boolean isStatic() default true;
 
     /**
-     * Gets the {@linkplain MetaUtil#signatureToMethodDescriptor signature} of the original method.
+     * Gets the {@linkplain Signature#toMethodDescriptor signature} of the original method.
      * <p>
      * If the default value is specified for this element, then the signature of the original method
      * is the same as the substitute method.
@@ -58,7 +58,7 @@
     /**
      * Determines if this method should be substituted in all cases, even if inlining thinks it is
      * not important.
-     * 
+     *
      * Note that this is still depending on whether inlining sees the correct call target, so it's
      * only a hard guarantee for static and special invocations.
      */
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Tue Jul 15 19:21:28 2014 -0700
@@ -86,8 +86,8 @@
     @Override
     protected void build() {
         if (PrintProfilingInformation.getValue()) {
-            TTY.println("Profiling info for " + MetaUtil.format("%H.%n(%p)", method));
-            TTY.println(MetaUtil.indent(MetaUtil.profileToString(profilingInfo, method, CodeUtil.NEW_LINE), "  "));
+            TTY.println("Profiling info for " + method.format("%H.%n(%p)"));
+            TTY.println(MetaUtil.indent(profilingInfo.toString(method, CodeUtil.NEW_LINE), "  "));
         }
 
         try (Indent indent = Debug.logAndIndent("build graph for %s", method)) {
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineControlFlowGraph.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineControlFlowGraph.java	Tue Jul 15 19:21:28 2014 -0700
@@ -39,6 +39,10 @@
         try (Scope ds = Debug.scope("BaselineCFG", blockMap)) {
             BaselineControlFlowGraph cfg = new BaselineControlFlowGraph(blockMap);
             cfg.computeLoopInformation(blockMap);
+            AbstractControlFlowGraph.computeDominators(cfg);
+
+            assert CFGVerifier.verify(cfg);
+
             return cfg;
         } catch (Throwable e) {
             throw Debug.handle(e);
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlock.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlock.java	Tue Jul 15 19:21:28 2014 -0700
@@ -58,28 +58,14 @@
 
     T getDominator();
 
+    void setDominator(T block);
+
+    List<T> getDominated();
+
+    void setDominated(List<T> blocks);
+
+    T getPostdominator();
+
     double probability();
 
-    /**
-     * True if block {@code a} dominates block {@code b}.
-     */
-    static boolean dominates(AbstractBlock<?> a, AbstractBlock<?> b) {
-        assert a != null;
-        return isDominatedBy(b, a);
-    }
-
-    /**
-     * True if block {@code a} is dominated by block {@code b}.
-     */
-    static boolean isDominatedBy(AbstractBlock<?> a, AbstractBlock<?> b) {
-        assert a != null;
-        if (a == b) {
-            return true;
-        }
-        if (a.getDominator() == null) {
-            return false;
-        }
-        return isDominatedBy(a.getDominator(), b);
-    }
-
 }
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlockBase.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlockBase.java	Tue Jul 15 19:21:28 2014 -0700
@@ -32,6 +32,7 @@
     protected List<T> successors;
 
     private T dominator;
+    private List<T> dominated;
 
     private boolean align;
     private int linearScanNumber;
@@ -73,6 +74,17 @@
         this.dominator = dominator;
     }
 
+    public List<T> getDominated() {
+        if (dominated == null) {
+            return Collections.emptyList();
+        }
+        return dominated;
+    }
+
+    public void setDominated(List<T> blocks) {
+        dominated = blocks;
+    }
+
     @Override
     public String toString() {
         return "B" + id;
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractControlFlowGraph.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractControlFlowGraph.java	Tue Jul 15 19:21:28 2014 -0700
@@ -29,9 +29,99 @@
     static final int BLOCK_ID_INITIAL = -1;
     static final int BLOCK_ID_VISITED = -2;
 
+    /**
+     * Returns the list blocks contained in this control flow graph.
+     *
+     * It is {@linkplain CFGVerifier guaranteed} that the blocks are numbered and ordered according
+     * to a reverse post order traversal of the control flow graph.
+     *
+     * @see CFGVerifier
+     */
     List<T> getBlocks();
 
     Collection<Loop<T>> getLoops();
 
     T getStartBlock();
+
+    /**
+     * Computes the dominators of control flow graph.
+     */
+    static <T extends AbstractBlock<T>> void computeDominators(AbstractControlFlowGraph<T> cfg) {
+        List<T> reversePostOrder = cfg.getBlocks();
+        assert reversePostOrder.get(0).getPredecessorCount() == 0 : "start block has no predecessor and therefore no dominator";
+        for (int i = 1; i < reversePostOrder.size(); i++) {
+            T block = reversePostOrder.get(i);
+            assert block.getPredecessorCount() > 0;
+            T dominator = null;
+            for (T pred : block.getPredecessors()) {
+                if (!pred.isLoopEnd()) {
+                    dominator = commonDominatorTyped(dominator, pred);
+                }
+            }
+            // set dominator
+            block.setDominator(dominator);
+            if (dominator.getDominated().equals(Collections.emptyList())) {
+                dominator.setDominated(new ArrayList<>());
+            }
+            dominator.getDominated().add(block);
+        }
+    }
+
+    /**
+     * True if block {@code a} is dominated by block {@code b}.
+     */
+    static boolean isDominatedBy(AbstractBlock<?> a, AbstractBlock<?> b) {
+        assert a != null;
+        if (a == b) {
+            return true;
+        }
+        if (a.getDominator() == null) {
+            return false;
+        }
+        return isDominatedBy(a.getDominator(), b);
+    }
+
+    /**
+     * True if block {@code a} dominates block {@code b}.
+     */
+    static boolean dominates(AbstractBlock<?> a, AbstractBlock<?> b) {
+        assert a != null;
+        return isDominatedBy(b, a);
+    }
+
+    /**
+     * Calculates the common dominator of two blocks.
+     *
+     * Note that this algorithm makes use of special properties regarding the numbering of blocks.
+     *
+     * @see #getBlocks()
+     * @see CFGVerifier
+     */
+    public static AbstractBlock<?> commonDominator(AbstractBlock<?> a, AbstractBlock<?> b) {
+        if (a == null) {
+            return b;
+        }
+        if (b == null) {
+            return a;
+        }
+        AbstractBlock<?> iterA = a;
+        AbstractBlock<?> iterB = b;
+        while (iterA != iterB) {
+            if (iterA.getId() > iterB.getId()) {
+                iterA = iterA.getDominator();
+            } else {
+                assert iterB.getId() > iterA.getId();
+                iterB = iterB.getDominator();
+            }
+        }
+        return iterA;
+    }
+
+    /**
+     * @see AbstractControlFlowGraph#commonDominator(AbstractBlock, AbstractBlock)
+     */
+    @SuppressWarnings("unchecked")
+    public static <T extends AbstractBlock<T>> T commonDominatorTyped(T a, T b) {
+        return (T) commonDominator(a, b);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/CFGVerifier.java	Tue Jul 15 19:21:28 2014 -0700
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2012, 2014, 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.compiler.common.cfg;
+
+import java.util.*;
+
+public class CFGVerifier {
+
+    public static <T extends AbstractBlock<T>, C extends AbstractControlFlowGraph<T>> boolean verify(C cfg) {
+        for (T block : cfg.getBlocks()) {
+            assert block.getId() >= 0;
+            assert cfg.getBlocks().get(block.getId()) == block;
+
+            for (T pred : block.getPredecessors()) {
+                assert pred.getSuccessors().contains(block);
+                assert pred.getId() < block.getId() || pred.isLoopEnd();
+            }
+
+            for (T sux : block.getSuccessors()) {
+                assert sux.getPredecessors().contains(block);
+                assert sux.getId() > block.getId() || sux.isLoopHeader();
+            }
+
+            if (block.getDominator() != null) {
+                assert block.getDominator().getId() < block.getId();
+                assert block.getDominator().getDominated().contains(block);
+            }
+            for (T dominated : block.getDominated()) {
+                assert dominated.getId() > block.getId();
+                assert dominated.getDominator() == block;
+            }
+
+            T postDominatorBlock = block.getPostdominator();
+            if (postDominatorBlock != null) {
+                assert block.getSuccessorCount() > 0 : "block has post-dominator block, but no successors";
+
+                BlockMap<Boolean> visitedBlocks = new BlockMap<>(cfg);
+                visitedBlocks.put(block, true);
+
+                Deque<T> stack = new ArrayDeque<>();
+                for (T sux : block.getSuccessors()) {
+                    visitedBlocks.put(sux, true);
+                    stack.push(sux);
+                }
+
+                while (stack.size() > 0) {
+                    T tos = stack.pop();
+                    assert tos.getId() <= postDominatorBlock.getId();
+                    if (tos == postDominatorBlock) {
+                        continue; // found a valid path
+                    }
+                    assert tos.getSuccessorCount() > 0 : "no path found";
+
+                    for (T sux : tos.getSuccessors()) {
+                        if (visitedBlocks.get(sux) == null) {
+                            visitedBlocks.put(sux, true);
+                            stack.push(sux);
+                        }
+                    }
+                }
+            }
+
+            assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().getHeader() == block;
+        }
+
+        if (cfg.getLoops() != null) {
+            for (Loop<T> loop : cfg.getLoops()) {
+                assert loop.getHeader().isLoopHeader();
+
+                for (T block : loop.getBlocks()) {
+                    assert block.getId() >= loop.getHeader().getId();
+
+                    Loop<?> blockLoop = block.getLoop();
+                    while (blockLoop != loop) {
+                        assert blockLoop != null;
+                        blockLoop = blockLoop.getParent();
+                    }
+
+                    if (!(block.isLoopHeader() && block.getLoop() == loop)) {
+                        for (T pred : block.getPredecessors()) {
+                            if (!loop.getBlocks().contains(pred)) {
+                                assert false : "Loop " + loop + " does not contain " + pred;
+                                return false;
+                            }
+                        }
+                    }
+                }
+
+                for (T block : loop.getExits()) {
+                    assert block.getId() >= loop.getHeader().getId();
+
+                    Loop<?> blockLoop = block.getLoop();
+                    while (blockLoop != null) {
+                        blockLoop = blockLoop.getParent();
+                        assert blockLoop != loop;
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java	Tue Jul 15 19:21:28 2014 -0700
@@ -47,12 +47,12 @@
 
     @Override
     protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw GraalInternalError.unimplemented(MetaUtil.format("direct call to %H.%n(%p)", callTarget.target()));
+        throw GraalInternalError.unimplemented(callTarget.target().format("direct call to %H.%n(%p)"));
     }
 
     @Override
     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw GraalInternalError.unimplemented(MetaUtil.format("direct call to %H.%n(%p)", callTarget.target()));
+        throw GraalInternalError.unimplemented(callTarget.target().format("direct call to %H.%n(%p)"));
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java	Tue Jul 15 19:21:28 2014 -0700
@@ -83,7 +83,7 @@
             if (!Modifier.isStatic(graph.method().getModifiers())) {
                 parameterIndex--;
             }
-            Warp warpAnnotation = parameterIndex >= 0 ? MetaUtil.getParameterAnnotation(Warp.class, parameterIndex, graph.method()) : null;
+            Warp warpAnnotation = parameterIndex >= 0 ? graph.method().getParameterAnnotation(Warp.class, parameterIndex) : null;
             if (warpAnnotation != null) {
                 setResult(param, getGen().emitWarpParam(paramValue.getKind().getStackKind(), warpAnnotation));
             } else {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java	Tue Jul 15 19:21:28 2014 -0700
@@ -384,7 +384,7 @@
 
     public StructuredGraph visualize(StructuredGraph graph, String title) {
         DebugConfig debugConfig = DebugScope.getConfig();
-        DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output());
+        DebugConfig fixedConfig = Debug.fixedConfig(0, Debug.DEFAULT_LOG_LEVEL, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output());
         try (DebugConfigScope s = Debug.setConfig(fixedConfig)) {
             Debug.dump(graph, title);
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Jul 15 19:21:28 2014 -0700
@@ -475,7 +475,7 @@
             try (Scope s = Debug.scope("CodeInstall", getCodeCache(), javaMethod)) {
                 installedCode = addMethod(javaMethod, compResult);
                 if (installedCode == null) {
-                    throw new GraalInternalError("Could not install code for " + MetaUtil.format("%H.%n(%p)", javaMethod));
+                    throw new GraalInternalError("Could not install code for " + javaMethod.format("%H.%n(%p)"));
                 }
             } catch (Throwable e) {
                 throw Debug.handle(e);
@@ -501,7 +501,7 @@
     }
 
     protected void checkArgs(ResolvedJavaMethod method, Object[] args) {
-        JavaType[] sig = MetaUtil.signatureToTypes(method);
+        JavaType[] sig = method.toParameterTypes();
         Assert.assertEquals(sig.length, args.length);
         for (int i = 0; i < args.length; i++) {
             JavaType javaType = sig[i];
@@ -637,7 +637,7 @@
             try (Scope s = Debug.scope("CodeInstall", getCodeCache(), method)) {
                 installedCode = addMethod(method, compResult);
                 if (installedCode == null) {
-                    throw new GraalInternalError("Could not install code for " + MetaUtil.format("%H.%n(%p)", method));
+                    throw new GraalInternalError("Could not install code for " + method.format("%H.%n(%p)"));
                 }
             } catch (Throwable e) {
                 throw Debug.handle(e);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Tue Jul 15 19:21:28 2014 -0700
@@ -464,28 +464,7 @@
         assertReadAndWriteInSameBlock(schedule, false);
     }
 
-    /*
-     * read of field a should be in first block, read of field b in loop begin block
-     */
-    public static void testProxy1Snippet() {
-        while (container.a < container.b) {
-            container.b--;
-        }
-        container.b++;
-    }
-
-    @Test
-    public void testProxy1() {
-        SchedulePhase schedule = getFinalSchedule("testProxy1Snippet", TestMode.WITHOUT_FRAMESTATES);
-        assertReadWithinStartBlock(schedule, true); // read of container.a should be in start block
-        /*
-         * read of container.b for increment operation should be in return block. TODO: not sure
-         * though, could be replaced by read of container.b of the loop header...
-         */
-        assertReadWithinAllReturnBlocks(schedule, true);
-    }
-
-    public static void testProxy2Snippet() {
+    public static void testProxySnippet() {
         while (container.a < container.b) {
             List<Container> list = new ArrayList<>(containerList);
             while (container.c < list.size()) {
@@ -501,8 +480,8 @@
     }
 
     @Test
-    public void testProxy2() {
-        SchedulePhase schedule = getFinalSchedule("testProxy2Snippet", TestMode.WITHOUT_FRAMESTATES);
+    public void testProxy() {
+        SchedulePhase schedule = getFinalSchedule("testProxySnippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, false);
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java	Tue Jul 15 19:21:28 2014 -0700
@@ -35,52 +35,52 @@
  * <p>
  * These options enable the associated debug facility if their filter matches the
  * {@linkplain DebugScope#getQualifiedName() name} of the {@linkplain Debug#currentScope() current
- * scope}.
+ * scope}. For the {@link GraalDebugConfig#Dump} and {@link GraalDebugConfig#Log} options, the log
+ * or dump level is set. The {@link GraalDebugConfig#Meter} and {@link GraalDebugConfig#Time}
+ * options don't have a level, for them {@code level = 0} means disabled and a {@code level > 0}
+ * means enabled.
  * <p>
- * A filter is a list of comma-separated terms. Each term is interpreted as a glob pattern if it
- * contains a "*" or "?" character. Otherwise, it is interpreted as a substring. If a term starts
- * with "~", then it is an positive term. An input is matched by a filter if any of its positive
- * terms match the input (or it has no positive terms) AND none of its negative terms match the
- * input (or it has no negative terms).
+ * A filter is a list of comma-separated terms of the form {@code <pattern>[:<level>]}.
+ * {@code <pattern>} is interpreted as a glob pattern if it contains a "*" or "?" character.
+ * Otherwise, it is interpreted as a substring. If {@code <pattern>} is empty, it matches every
+ * scope. If {@code :<level>} is omitted, it defaults to {@link Debug#DEFAULT_LOG_LEVEL}. The term
+ * {@code ~<pattern>} is a shorthand for {@code <pattern>:0} to disable a debug facility for a
+ * pattern.
  * <p>
- * Examples of filters include:
- * <p>
+ * The resulting log level of a scope is determined by the <em>last</em> matching term. If no term
+ * matches, the log level is 0 (disabled). A filter with no terms matches every scope with a log
+ * level of {@link Debug#DEFAULT_LOG_LEVEL}.
+ *
+ * <h2>Examples of filters</h2>
+ *
  * <ul>
- * <li>
- * 
- * <pre>
- * &quot;&quot;
- * </pre>
- * 
- * Matches any scope.</li>
- * <li>
- * 
- * <pre>
- * &quot;*&quot;
- * </pre>
- * 
- * Matches any scope.</li>
- * <li>
- * 
- * <pre>
- * &quot;CodeGen,CodeInstall&quot;
- * </pre>
- * 
- * Matches a scope whose name contains "CodeGen" or "CodeInstall".</li>
- * <li>
- * 
- * <pre>
- * &quot;Code*&quot;
- * </pre>
- * 
- * Matches a scope whose name starts with "Code".</li>
- * <li>
- * 
- * <pre>
- * &quot;Code,&tilde;Dead&quot;
- * </pre>
- * 
- * Matches a scope whose name contains "Code" but does not contain "Dead".</li>
+ * <li>(empty string)<br>
+ * Matches any scope with log level {@link Debug#DEFAULT_LOG_LEVEL}.
+ *
+ * <li> {@code :1}<br>
+ * Matches any scope with log level 1.
+ *
+ * <li> {@code *}<br>
+ * Matches any scope with log level {@link Debug#DEFAULT_LOG_LEVEL}.
+ *
+ * <li> {@code CodeGen,CodeInstall}<br>
+ * Matches scopes containing "CodeGen" or "CodeInstall", both with log level
+ * {@link Debug#DEFAULT_LOG_LEVEL}.
+ *
+ * <li> {@code CodeGen:2,CodeInstall:1}<br>
+ * Matches scopes containing "CodeGen" with log level 2, or "CodeInstall" with log level 1.
+ *
+ * <li> {@code :1,Dead:2}<br>
+ * Matches scopes containing "Dead" with log level 2, and all other scopes with log level 1.
+ *
+ * <li> {@code :1,Dead:0}<br>
+ * Matches all scopes with log level 1, except those containing "Dead".
+ *
+ * <li> {@code Code*}<br>
+ * Matches scopes starting with "Code" with log level {@link Debug#DEFAULT_LOG_LEVEL}.
+ *
+ * <li> {@code Code,~Dead}<br>
+ * Matches scopes containing "Code" but not "Dead", with log level {@link Debug#DEFAULT_LOG_LEVEL}.
  * </ul>
  */
 class DebugFilter {
@@ -92,69 +92,76 @@
         return new DebugFilter(spec.split(","));
     }
 
-    final Term[] positive;
-    final Term[] negative;
+    private final Term[] terms;
+
+    private DebugFilter(String[] terms) {
+        if (terms.length == 0) {
+            this.terms = null;
+        } else {
+            this.terms = new Term[terms.length];
+            for (int i = 0; i < terms.length; i++) {
+                String t = terms[i];
+                int idx = t.indexOf(':');
 
-    DebugFilter(String[] terms) {
-        List<Term> pos = new ArrayList<>(terms.length);
-        List<Term> neg = new ArrayList<>(terms.length);
-        for (int i = 0; i < terms.length; i++) {
-            String t = terms[i];
-            if (t.startsWith("~")) {
-                neg.add(new Term(t.substring(1)));
-            } else {
-                pos.add(new Term(t));
+                String pattern;
+                int level;
+                if (idx < 0) {
+                    if (t.startsWith("~")) {
+                        pattern = t.substring(1);
+                        level = 0;
+                    } else {
+                        pattern = t;
+                        level = Debug.DEFAULT_LOG_LEVEL;
+                    }
+                } else {
+                    pattern = t.substring(0, idx);
+                    if (idx + 1 < t.length()) {
+                        level = Integer.parseInt(t.substring(idx + 1));
+                    } else {
+                        level = Debug.DEFAULT_LOG_LEVEL;
+                    }
+                }
+
+                this.terms[i] = new Term(pattern, level);
             }
         }
-        this.positive = pos.isEmpty() ? null : pos.toArray(new Term[pos.size()]);
-        this.negative = neg.isEmpty() ? null : neg.toArray(new Term[neg.size()]);
     }
 
     /**
-     * Determines if a given input is matched by this filter.
+     * Check whether a given input is matched by this filter, and determine the log level.
      */
-    public boolean matches(String input) {
-        boolean match = true;
-        if (positive != null) {
-            match = false;
-            for (Term t : positive) {
+    public int matchLevel(String input) {
+        if (terms == null) {
+            return Debug.DEFAULT_LOG_LEVEL;
+        } else {
+            int level = 0;
+            for (Term t : terms) {
                 if (t.matches(input)) {
-                    match = true;
-                    break;
+                    level = t.level;
                 }
             }
+            return level;
         }
-        if (match && negative != null) {
-            for (Term t : negative) {
-                if (t.matches(input)) {
-                    match = false;
-                    break;
-                }
-            }
-        }
-        return match;
     }
 
     @Override
     public String toString() {
-        StringBuilder buf = new StringBuilder("DebugFilter[");
-        String sep = "";
-        if (positive != null) {
-            buf.append(sep).append("pos=").append(Arrays.toString(positive));
-            sep = ", ";
+        StringBuilder buf = new StringBuilder("DebugFilter");
+        if (terms != null) {
+            buf.append(Arrays.toString(terms));
+        } else {
+            buf.append("[]");
         }
-        if (negative != null) {
-            buf.append(sep).append("neg=").append(Arrays.toString(negative));
-            sep = ", ";
-        }
-        return buf.append("]").toString();
+        return buf.toString();
     }
 
-    static class Term {
+    private static class Term {
 
-        final Pattern pattern;
+        private final Pattern pattern;
+        public final int level;
 
-        public Term(String filter) {
+        public Term(String filter, int level) {
+            this.level = level;
             if (filter.isEmpty()) {
                 this.pattern = null;
             } else if (filter.contains("*") || filter.contains("?")) {
@@ -173,7 +180,7 @@
 
         @Override
         public String toString() {
-            return pattern == null ? ".*" : pattern.toString();
+            return (pattern == null ? ".*" : pattern.toString()) + ":" + level;
         }
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Jul 15 19:21:28 2014 -0700
@@ -121,8 +121,8 @@
         this.output = output;
     }
 
-    public boolean isLogEnabled() {
-        return isEnabled(logFilter);
+    public int getLogLevel() {
+        return getLevel(logFilter);
     }
 
     public boolean isLogEnabledForMethod() {
@@ -137,8 +137,8 @@
         return isEnabled(trackMemUseFilter);
     }
 
-    public boolean isDumpEnabled() {
-        return isEnabled(dumpFilter);
+    public int getDumpLevel() {
+        return getLevel(dumpFilter);
     }
 
     public boolean isDumpEnabledForMethod() {
@@ -162,15 +162,27 @@
     }
 
     private boolean isEnabled(DebugFilter filter) {
-        return checkDebugFilter(Debug.currentScope(), filter) && checkMethodFilter();
+        return getLevel(filter) > 0;
+    }
+
+    private int getLevel(DebugFilter filter) {
+        int level = checkDebugFilter(Debug.currentScope(), filter);
+        if (level > 0 && !checkMethodFilter()) {
+            level = 0;
+        }
+        return level;
     }
 
     private boolean isEnabledForMethod(DebugFilter filter) {
         return filter != null && checkMethodFilter();
     }
 
-    private static boolean checkDebugFilter(String currentScope, DebugFilter filter) {
-        return filter != null && filter.matches(currentScope);
+    private static int checkDebugFilter(String currentScope, DebugFilter filter) {
+        if (filter == null) {
+            return 0;
+        } else {
+            return filter.matchLevel(currentScope);
+        }
     }
 
     /**
@@ -241,7 +253,7 @@
         if (e instanceof BailoutException) {
             return null;
         }
-        Debug.setConfig(Debug.fixedConfig(true, true, false, false, false, false, dumpHandlers, verifyHandlers, output));
+        Debug.setConfig(Debug.fixedConfig(Debug.DEFAULT_LOG_LEVEL, Debug.DEFAULT_LOG_LEVEL, false, false, false, false, dumpHandlers, verifyHandlers, output));
         Debug.log(String.format("Exception occurred in scope: %s", Debug.currentScope()));
         for (Object o : Debug.context()) {
             if (o instanceof Graph) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/MethodFilter.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/MethodFilter.java	Tue Jul 15 19:21:28 2014 -0700
@@ -171,7 +171,7 @@
         if (methodName != null && !methodName.matcher(o.getName()).matches()) {
             return false;
         }
-        if (clazz != null && !clazz.matcher(MetaUtil.toJavaName(o.getDeclaringClass())).matches()) {
+        if (clazz != null && !clazz.matcher(o.getDeclaringClass().toJavaName()).matches()) {
             return false;
         }
         if (signature != null) {
@@ -181,7 +181,7 @@
             }
             for (int i = 0; i < signature.length; i++) {
                 JavaType type = sig.getParameterType(i, null);
-                String javaName = MetaUtil.toJavaName(type);
+                String javaName = type.toJavaName();
                 if (signature[i] != null && !signature[i].matcher(javaName).matches()) {
                     return false;
                 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Jul 15 19:21:28 2014 -0700
@@ -25,7 +25,7 @@
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.compiler.GraalDebugConfig.*;
-import static com.oracle.graal.compiler.common.cfg.AbstractBlock.*;
+import static com.oracle.graal.compiler.common.cfg.AbstractControlFlowGraph.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
 
 import java.util.*;
@@ -1720,7 +1720,7 @@
                 } else {
                     AbstractBlock<?> spillBlock = blockForId(spillPos);
                     if (interval.alwaysInMemory() && !interval.location().equals(interval.spillSlot())) {
-                        if ((spillBlock.equals(block) && op.id() > spillPos) || AbstractBlock.dominates(spillBlock, block)) {
+                        if ((spillBlock.equals(block) && op.id() > spillPos) || dominates(spillBlock, block)) {
                             assert spillPos > 0 : "position not set correctly";
                             assert interval.spillSlot() != null : "no spill slot assigned";
                             assert !isRegister(interval.operand) : "interval is on stack :  so stack slot is registered twice";
@@ -1956,7 +1956,7 @@
                                     if (spillBlock == null) {
                                         spillBlock = splitBlock;
                                     } else {
-                                        spillBlock = nearestCommonDominator(spillBlock, splitBlock);
+                                        spillBlock = commonDominator(spillBlock, splitBlock);
                                         assert spillBlock != null;
                                     }
                                 }
@@ -2086,35 +2086,6 @@
         return defBlock;
     }
 
-    private AbstractBlock<?> nearestCommonDominator(AbstractBlock<?> a, AbstractBlock<?> b) {
-        assert a != null;
-        assert b != null;
-        try (Indent indent = Debug.logAndIndent("nearest common dominator of %s and %s", a, b)) {
-
-            if (a.equals(b)) {
-                return a;
-            }
-
-            // collect a's dominators
-            BitSet aDom = new BitSet(sortedBlocks.size());
-
-            // a != b
-            for (AbstractBlock<?> x = a; x != null; x = x.getDominator()) {
-                aDom.set(x.getId());
-            }
-
-            // walk b's dominator
-            for (AbstractBlock<?> x = b; x != null; x = x.getDominator()) {
-                if (aDom.get(x.getId())) {
-                    Debug.log("found %s", x);
-                    return x;
-                }
-            }
-        }
-        Debug.log("no common dominator found");
-        return null;
-    }
-
     void printIntervals(String label) {
         if (Debug.isLogEnabled()) {
             try (Indent indent = Debug.logAndIndent("intervals %s", label)) {
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Tue Jul 15 19:21:28 2014 -0700
@@ -82,8 +82,14 @@
         return config.isDumpEnabledForMethod();
     }
 
+    public static final int DEFAULT_LOG_LEVEL = 2;
+
     public static boolean isDumpEnabled() {
-        return ENABLED && DebugScope.getInstance().isDumpEnabled();
+        return isDumpEnabled(DEFAULT_LOG_LEVEL);
+    }
+
+    public static boolean isDumpEnabled(int dumpLevel) {
+        return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel);
     }
 
     /**
@@ -137,7 +143,11 @@
     }
 
     public static boolean isLogEnabled() {
-        return ENABLED && DebugScope.getInstance().isLogEnabled();
+        return isLogEnabled(DEFAULT_LOG_LEVEL);
+    }
+
+    public static boolean isLogEnabled(int logLevel) {
+        return ENABLED && DebugScope.getInstance().isLogEnabled(logLevel);
     }
 
     @SuppressWarnings("unused")
@@ -352,74 +362,106 @@
         }
     }
 
+    public static void log(String msg) {
+        log(DEFAULT_LOG_LEVEL, msg);
+    }
+
     /**
      * Prints a message to the current debug scope's logging stream if logging is enabled.
      *
      * @param msg the message to log
      */
-    public static void log(String msg) {
+    public static void log(int logLevel, String msg) {
         if (ENABLED) {
-            DebugScope.getInstance().log(msg);
+            DebugScope.getInstance().log(logLevel, msg);
         }
     }
 
+    public static void log(String format, Object arg) {
+        log(DEFAULT_LOG_LEVEL, format, arg);
+    }
+
     /**
      * Prints a message to the current debug scope's logging stream if logging is enabled.
      *
      * @param format a format string
      * @param arg the argument referenced by the format specifiers in {@code format}
      */
-    public static void log(String format, Object arg) {
+    public static void log(int logLevel, String format, Object arg) {
         if (ENABLED) {
-            DebugScope.getInstance().log(format, arg);
+            DebugScope.getInstance().log(logLevel, format, arg);
         }
     }
 
+    public static void log(String format, Object arg1, Object arg2) {
+        log(DEFAULT_LOG_LEVEL, format, arg1, arg2);
+    }
+
     /**
-     * @see #log(String, Object)
+     * @see #log(int, String, Object)
      */
-    public static void log(String format, Object arg1, Object arg2) {
+    public static void log(int logLevel, String format, Object arg1, Object arg2) {
         if (ENABLED) {
-            DebugScope.getInstance().log(format, arg1, arg2);
+            DebugScope.getInstance().log(logLevel, format, arg1, arg2);
         }
     }
 
+    public static void log(String format, Object arg1, Object arg2, Object arg3) {
+        log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3);
+    }
+
     /**
-     * @see #log(String, Object)
+     * @see #log(int, String, Object)
      */
-    public static void log(String format, Object arg1, Object arg2, Object arg3) {
+    public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3) {
         if (ENABLED) {
-            DebugScope.getInstance().log(format, arg1, arg2, arg3);
+            DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3);
         }
     }
 
+    public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) {
+        log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3, arg4);
+    }
+
     /**
-     * @see #log(String, Object)
+     * @see #log(int, String, Object)
      */
-    public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) {
+    public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4) {
         if (ENABLED) {
-            DebugScope.getInstance().log(format, arg1, arg2, arg3, arg4);
+            DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4);
         }
     }
 
+    public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
+        log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5);
+    }
+
     /**
-     * @see #log(String, Object)
+     * @see #log(int, String, Object)
      */
-    public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
+    public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
         if (ENABLED) {
-            DebugScope.getInstance().log(format, arg1, arg2, arg3, arg4, arg5);
+            DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5);
         }
     }
 
+    public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) {
+        log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
     /**
-     * @see #log(String, Object)
+     * @see #log(int, String, Object)
      */
-    public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) {
+    public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) {
         if (ENABLED) {
-            DebugScope.getInstance().log(format, arg1, arg2, arg3, arg4, arg5, arg6);
+            DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6);
         }
     }
 
+    public static void logv(String format, Object... args) {
+        logv(DEFAULT_LOG_LEVEL, format, args);
+    }
+
     /**
      * Prints a message to the current debug scope's logging stream. This method must only be called
      * if debugging is {@linkplain Debug#isEnabled() enabled} as it incurs allocation at the call
@@ -429,11 +471,11 @@
      * @param format a format string
      * @param args the arguments referenced by the format specifiers in {@code format}
      */
-    public static void logv(String format, Object... args) {
+    public static void logv(int logLevel, String format, Object... args) {
         if (!ENABLED) {
             throw new InternalError("Use of Debug.logv() must be guarded by a test of Debug.isEnabled()");
         }
-        DebugScope.getInstance().log(format, args);
+        DebugScope.getInstance().log(logLevel, format, args);
     }
 
     /**
@@ -445,30 +487,58 @@
     @Deprecated
     public static void log(String format, Object[] args) {
         assert false : "shouldn't use this";
-        logv(format, args);
+        log(DEFAULT_LOG_LEVEL, format, args);
+    }
+
+    /**
+     * This override exists to catch cases when {@link #log(int, String, Object)} is called with one
+     * argument bound to a varargs method parameter. It will bind to this method instead of the
+     * single arg variant and produce a deprecation warning instead of silently wrapping the
+     * Object[] inside of another Object[].
+     */
+    @Deprecated
+    public static void log(int logLevel, String format, Object[] args) {
+        assert false : "shouldn't use this";
+        logv(logLevel, format, args);
     }
 
     public static void dump(Object object, String msg) {
-        if (ENABLED && DebugScope.getInstance().isDumpEnabled()) {
-            DebugScope.getInstance().dump(object, msg);
+        dump(DEFAULT_LOG_LEVEL, object, msg);
+    }
+
+    public static void dump(int dumpLevel, Object object, String msg) {
+        if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) {
+            DebugScope.getInstance().dump(dumpLevel, object, msg);
         }
     }
 
     public static void dump(Object object, String format, Object arg) {
-        if (ENABLED && DebugScope.getInstance().isDumpEnabled()) {
-            DebugScope.getInstance().dump(object, format, arg);
+        dump(DEFAULT_LOG_LEVEL, object, format, arg);
+    }
+
+    public static void dump(int dumpLevel, Object object, String format, Object arg) {
+        if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) {
+            DebugScope.getInstance().dump(dumpLevel, object, format, arg);
         }
     }
 
     public static void dump(Object object, String format, Object arg1, Object arg2) {
-        if (ENABLED && DebugScope.getInstance().isDumpEnabled()) {
-            DebugScope.getInstance().dump(object, format, arg1, arg2);
+        dump(DEFAULT_LOG_LEVEL, object, format, arg1, arg2);
+    }
+
+    public static void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2) {
+        if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) {
+            DebugScope.getInstance().dump(dumpLevel, object, format, arg1, arg2);
         }
     }
 
     public static void dump(Object object, String format, Object arg1, Object arg2, Object arg3) {
-        if (ENABLED && DebugScope.getInstance().isDumpEnabled()) {
-            DebugScope.getInstance().dump(object, format, arg1, arg2, arg3);
+        dump(DEFAULT_LOG_LEVEL, object, format, arg1, arg2, arg3);
+    }
+
+    public static void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2, Object arg3) {
+        if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) {
+            DebugScope.getInstance().dump(dumpLevel, object, format, arg1, arg2, arg3);
         }
     }
 
@@ -481,8 +551,20 @@
     @Deprecated
     public static void dump(Object object, String format, Object[] args) {
         assert false : "shouldn't use this";
-        if (ENABLED && DebugScope.getInstance().isDumpEnabled()) {
-            DebugScope.getInstance().dump(object, format, args);
+        dump(DEFAULT_LOG_LEVEL, object, format, args);
+    }
+
+    /**
+     * This override exists to catch cases when {@link #dump(int, Object, String, Object)} is called
+     * with one argument bound to a varargs method parameter. It will bind to this method instead of
+     * the single arg variant and produce a deprecation warning instead of silently wrapping the
+     * Object[] inside of another Object[].
+     */
+    @Deprecated
+    public static void dump(int dumpLevel, Object object, String format, Object[] args) {
+        assert false : "shouldn't use this";
+        if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) {
+            DebugScope.getInstance().dump(dumpLevel, object, format, args);
         }
     }
 
@@ -537,8 +619,8 @@
      *
      * @return an object that reverts to the current indentation level when
      *         {@linkplain Indent#close() closed} or null if debugging is disabled
-     * @see #logAndIndent(String)
-     * @see #logAndIndent(String, Object)
+     * @see #logAndIndent(int, String)
+     * @see #logAndIndent(int, String, Object)
      */
     public static Indent indent() {
         if (ENABLED) {
@@ -548,6 +630,10 @@
         return null;
     }
 
+    public static Indent logAndIndent(String msg) {
+        return logAndIndent(DEFAULT_LOG_LEVEL, msg);
+    }
+
     /**
      * A convenience function which combines {@link #log(String)} and {@link #indent()}.
      *
@@ -555,13 +641,17 @@
      * @return an object that reverts to the current indentation level when
      *         {@linkplain Indent#close() closed} or null if debugging is disabled
      */
-    public static Indent logAndIndent(String msg) {
+    public static Indent logAndIndent(int logLevel, String msg) {
         if (ENABLED) {
-            return logvAndIndent(msg);
+            return logvAndIndent(logLevel, msg);
         }
         return null;
     }
 
+    public static Indent logAndIndent(String format, Object arg) {
+        return logAndIndent(DEFAULT_LOG_LEVEL, format, arg);
+    }
+
     /**
      * A convenience function which combines {@link #log(String, Object)} and {@link #indent()}.
      *
@@ -570,45 +660,54 @@
      * @return an object that reverts to the current indentation level when
      *         {@linkplain Indent#close() closed} or null if debugging is disabled
      */
-    public static Indent logAndIndent(String format, Object arg) {
+    public static Indent logAndIndent(int logLevel, String format, Object arg) {
+        if (ENABLED) {
+            return logvAndIndent(logLevel, format, arg);
+        }
+        return null;
+    }
+
+    public static Indent logAndIndent(String format, Object arg1, Object arg2) {
+        return logAndIndent(DEFAULT_LOG_LEVEL, format, arg1, arg2);
+    }
+
+    /**
+     * @see #logAndIndent(int, String, Object)
+     */
+    public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2) {
         if (ENABLED) {
-            return logvAndIndent(format, arg);
+            return logvAndIndent(logLevel, format, arg1, arg2);
+        }
+        return null;
+    }
+
+    public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3) {
+        return logAndIndent(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3);
+    }
+
+    /**
+     * @see #logAndIndent(int, String, Object)
+     */
+    public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3) {
+        if (ENABLED) {
+            return logvAndIndent(logLevel, format, arg1, arg2, arg3);
         }
         return null;
     }
 
     /**
-     * @see #logAndIndent(String, Object)
-     */
-    public static Indent logAndIndent(String format, Object arg1, Object arg2) {
-        if (ENABLED) {
-            return logvAndIndent(format, arg1, arg2);
-        }
-        return null;
-    }
-
-    /**
-     * @see #logAndIndent(String, Object)
-     */
-    public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3) {
-        if (ENABLED) {
-            return logvAndIndent(format, arg1, arg2, arg3);
-        }
-        return null;
-    }
-
-    /**
-     * A convenience function which combines {@link #logv(String, Object...)} and {@link #indent()}.
+     * A convenience function which combines {@link #logv(int, String, Object...)} and
+     * {@link #indent()}.
      *
      * @param format a format string
      * @param args the arguments referenced by the format specifiers in {@code format}
      * @return an object that reverts to the current indentation level when
      *         {@linkplain Indent#close() closed} or null if debugging is disabled
      */
-    public static Indent logvAndIndent(String format, Object... args) {
+    public static Indent logvAndIndent(int logLevel, String format, Object... args) {
         if (ENABLED) {
             DebugScope scope = DebugScope.getInstance();
-            scope.log(format, args);
+            scope.log(logLevel, format, args);
             return scope.pushIndentLogger();
         }
         throw new InternalError("Use of Debug.logvAndIndent() must be guarded by a test of Debug.isEnabled()");
@@ -623,7 +722,19 @@
     @Deprecated
     public static void logAndIndent(String format, Object[] args) {
         assert false : "shouldn't use this";
-        logvAndIndent(format, args);
+        logAndIndent(DEFAULT_LOG_LEVEL, format, args);
+    }
+
+    /**
+     * This override exists to catch cases when {@link #logAndIndent(int, String, Object)} is called
+     * with one argument bound to a varargs method parameter. It will bind to this method instead of
+     * the single arg variant and produce a deprecation warning instead of silently wrapping the
+     * Object[] inside of another Object[].
+     */
+    @Deprecated
+    public static void logAndIndent(int logLevel, String format, Object[] args) {
+        assert false : "shouldn't use this";
+        logvAndIndent(logLevel, format, args);
     }
 
     public static Iterable<Object> context() {
@@ -845,20 +956,20 @@
     }
 
     public static DebugConfig silentConfig() {
-        return fixedConfig(false, false, false, false, false, false, Collections.<DebugDumpHandler> emptyList(), Collections.<DebugVerifyHandler> emptyList(), null);
+        return fixedConfig(0, 0, false, false, false, false, Collections.<DebugDumpHandler> emptyList(), Collections.<DebugVerifyHandler> emptyList(), null);
     }
 
-    public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isMemUseTrackingEnabled, final boolean isTimerEnabled,
+    public static DebugConfig fixedConfig(final int logLevel, final int dumpLevel, final boolean isMeterEnabled, final boolean isMemUseTrackingEnabled, final boolean isTimerEnabled,
                     final boolean isVerifyEnabled, final Collection<DebugDumpHandler> dumpHandlers, final Collection<DebugVerifyHandler> verifyHandlers, final PrintStream output) {
         return new DebugConfig() {
 
             @Override
-            public boolean isLogEnabled() {
-                return isLogEnabled;
+            public int getLogLevel() {
+                return logLevel;
             }
 
             public boolean isLogEnabledForMethod() {
-                return isLogEnabled;
+                return logLevel > 0;
             }
 
             @Override
@@ -872,12 +983,12 @@
             }
 
             @Override
-            public boolean isDumpEnabled() {
-                return isDumpEnabled;
+            public int getDumpLevel() {
+                return dumpLevel;
             }
 
             public boolean isDumpEnabledForMethod() {
-                return isDumpEnabled;
+                return dumpLevel > 0;
             }
 
             @Override
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java	Tue Jul 15 19:21:28 2014 -0700
@@ -28,9 +28,16 @@
 public interface DebugConfig {
 
     /**
-     * Determines if logging is on in the {@linkplain Debug#currentScope() current debug scope} .
+     * Determines the current log level in the {@linkplain Debug#currentScope() current debug scope}
+     * .
      */
-    boolean isLogEnabled();
+    int getLogLevel();
+
+    /**
+     * Determines the current dump level in the {@linkplain Debug#currentScope() current debug
+     * scope}.
+     */
+    int getDumpLevel();
 
     /**
      * Determines if logging can be enabled in the current method, regardless of the
@@ -55,14 +62,6 @@
     boolean isMemUseTrackingEnabled();
 
     /**
-     * Determines if dumping is enabled in the {@linkplain Debug#currentScope() current debug scope}
-     * .
-     *
-     * @see Debug#dump(Object, String)
-     */
-    boolean isDumpEnabled();
-
-    /**
      * Determines if dumping can be enabled in the current method, regardless of the
      * {@linkplain Debug#currentScope() current debug scope}.
      */
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Tue Jul 15 19:21:28 2014 -0700
@@ -83,6 +83,18 @@
     private final Map<Feature, Boolean> featureState = new EnumMap<>(Feature.class);
 
     /**
+     * The debug levels of a {@link DelegatingDebugConfig} than can be
+     * {@linkplain DelegatingDebugConfig#override(Level, int) overridden} or
+     * {@linkplain DelegatingDebugConfig#delegate(Level) delegated}.
+     */
+    public enum Level {
+        LOG,
+        DUMP
+    }
+
+    private final Map<Level, Integer> levelState = new EnumMap<>(Level.class);
+
+    /**
      * Creates a config that delegates to the {@link DebugScope#getConfig() current config}.
      */
     public DelegatingDebugConfig() {
@@ -106,18 +118,28 @@
         return this;
     }
 
+    public DelegatingDebugConfig override(Level level, int newLevel) {
+        levelState.put(level, newLevel);
+        return this;
+    }
+
     public DelegatingDebugConfig delegate(Feature feature) {
         featureState.put(feature, null);
         return this;
     }
 
+    public DelegatingDebugConfig delegate(Level level) {
+        levelState.put(level, null);
+        return this;
+    }
+
     @Override
-    public boolean isLogEnabled() {
-        Boolean fs = featureState.get(Feature.LOG);
-        if (fs == null) {
-            return delegate.isLogEnabled();
+    public int getLogLevel() {
+        Integer ls = levelState.get(Level.LOG);
+        if (ls == null) {
+            return delegate.getLogLevel();
         }
-        return fs.booleanValue();
+        return ls.intValue();
     }
 
     public boolean isLogEnabledForMethod() {
@@ -146,12 +168,12 @@
     }
 
     @Override
-    public boolean isDumpEnabled() {
-        Boolean fs = featureState.get(Feature.DUMP);
-        if (fs == null) {
-            return delegate.isDumpEnabled();
+    public int getDumpLevel() {
+        Integer ls = levelState.get(Level.DUMP);
+        if (ls == null) {
+            return delegate.getDumpLevel();
         }
-        return fs.booleanValue();
+        return ls.intValue();
     }
 
     public boolean isDumpEnabledForMethod() {
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Tue Jul 15 19:21:28 2014 -0700
@@ -52,8 +52,8 @@
             }
         }
 
-        public void log(String msg, Object... args) {
-            if (isLogEnabled()) {
+        public void log(int logLevel, String msg, Object... args) {
+            if (isLogEnabled(logLevel)) {
                 StringBuilder str = new StringBuilder();
                 printScopeName(str);
                 str.append(indent);
@@ -102,9 +102,10 @@
     private boolean meterEnabled;
     private boolean timeEnabled;
     private boolean memUseTrackingEnabled;
-    private boolean dumpEnabled;
     private boolean verifyEnabled;
-    private boolean logEnabled;
+
+    private int currentDumpLevel;
+    private int currentLogLevel;
 
     private PrintStream output;
 
@@ -163,16 +164,18 @@
         lastClosedTL.set(this);
     }
 
-    public boolean isDumpEnabled() {
-        return dumpEnabled;
+    public boolean isDumpEnabled(int dumpLevel) {
+        assert dumpLevel > 0;
+        return currentDumpLevel >= dumpLevel;
     }
 
     public boolean isVerifyEnabled() {
         return verifyEnabled;
     }
 
-    public boolean isLogEnabled() {
-        return logEnabled;
+    public boolean isLogEnabled(int logLevel) {
+        assert logLevel > 0;
+        return currentLogLevel >= logLevel;
     }
 
     public boolean isMeterEnabled() {
@@ -187,12 +190,12 @@
         return memUseTrackingEnabled;
     }
 
-    public void log(String msg, Object... args) {
-        lastUsedIndent.log(msg, args);
+    public void log(int logLevel, String msg, Object... args) {
+        lastUsedIndent.log(logLevel, msg, args);
     }
 
-    public void dump(Object object, String formatString, Object... args) {
-        if (isDumpEnabled()) {
+    public void dump(int dumpLevel, Object object, String formatString, Object... args) {
+        if (isDumpEnabled(dumpLevel)) {
             DebugConfig config = getConfig();
             if (config != null) {
                 String message = String.format(formatString, args);
@@ -289,9 +292,10 @@
             meterEnabled = false;
             memUseTrackingEnabled = false;
             timeEnabled = false;
-            dumpEnabled = false;
             verifyEnabled = false;
 
+            currentDumpLevel = 0;
+
             // Be pragmatic: provide a default log stream to prevent a crash if the stream is not
             // set while logging
             output = TTY.cachedOut;
@@ -299,10 +303,10 @@
             meterEnabled = config.isMeterEnabled();
             memUseTrackingEnabled = config.isMemUseTrackingEnabled();
             timeEnabled = config.isTimeEnabled();
-            dumpEnabled = config.isDumpEnabled();
             verifyEnabled = config.isVerifyEnabled();
-            logEnabled = config.isLogEnabled();
             output = config.output();
+            currentDumpLevel = config.getDumpLevel();
+            currentLogLevel = config.getLogLevel();
         }
     }
 
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java	Tue Jul 15 19:21:28 2014 -0700
@@ -290,7 +290,7 @@
             args.add("hub", hub);
             args.add("prototypeMarkWord", type.prototypeMarkWord());
             args.addConst("fillContents", newInstanceNode.fillContents());
-            args.addConst("typeContext", MetaUtil.toJavaName(type, false));
+            args.addConst("typeContext", type.toJavaName(false));
 
             SnippetTemplate template = template(args);
             Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args);
@@ -320,7 +320,7 @@
             args.addConst("log2ElementSize", log2ElementSize);
             args.addConst("fillContents", newArrayNode.fillContents());
             args.addConst("maybeUnroll", length.isConstant());
-            args.addConst("typeContext", MetaUtil.toJavaName(arrayType, false));
+            args.addConst("typeContext", arrayType.toJavaName(false));
 
             SnippetTemplate template = template(args);
             Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Tue Jul 15 19:21:28 2014 -0700
@@ -25,12 +25,12 @@
 import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.api.meta.LocationIdentity.*;
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.asm.NumUtil.*;
 import static com.oracle.graal.hotspot.ptx.PTXHotSpotBackend.*;
 import static com.oracle.graal.hotspot.ptx.PTXWrapperBuilder.LaunchArg.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.ConstantNode.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -324,7 +324,7 @@
      */
     private void updateDimArg(ResolvedJavaMethod method, Signature sig, int sigIndex, Map<LaunchArg, ValueNode> launchArgs, ParameterNode javaParameter) {
         if (sigIndex >= 0) {
-            ParallelOver parallelOver = getParameterAnnotation(ParallelOver.class, sigIndex, method);
+            ParallelOver parallelOver = method.getParameterAnnotation(ParallelOver.class, sigIndex);
             if (parallelOver != null && sig.getParameterType(sigIndex, method.getDeclaringClass()).equals(providers.getMetaAccess().lookupJavaType(int[].class))) {
                 ArrayLengthNode dimension = append(new ArrayLengthNode(javaParameter));
                 LaunchArg argKey = LaunchArg.valueOf(LaunchArg.class, "Dim" + parallelOver.dimension());
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.test;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static java.lang.reflect.Modifier.*;
 
 import java.lang.reflect.*;
@@ -85,7 +84,7 @@
         if (argsToBind != null) {
             Object receiver = isStatic(m.getModifiers()) ? null : this;
             Object[] args = argsWithReceiver(receiver, argsToBind);
-            JavaType[] parameterTypes = signatureToTypes(getMetaAccess().lookupJavaMethod(m));
+            JavaType[] parameterTypes = getMetaAccess().lookupJavaMethod(m).toParameterTypes();
             assert parameterTypes.length == args.length;
             for (int i = 0; i < argsToBind.length; i++) {
                 ParameterNode param = graph.getParameter(i);
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Tue Jul 15 19:21:28 2014 -0700
@@ -692,7 +692,7 @@
             };
 
             DebugConfig debugConfig = DebugScope.getConfig();
-            DebugConfig fixedConfig = Debug.fixedConfig(false, false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output());
+            DebugConfig fixedConfig = Debug.fixedConfig(0, 0, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output());
             try (DebugConfigScope s = Debug.setConfig(fixedConfig)) {
                 ReentrantNodeIterator.apply(closure, graph.start(), false);
                 new WriteBarrierVerificationPhase().apply(graph);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java	Tue Jul 15 19:21:28 2014 -0700
@@ -86,7 +86,7 @@
         if (method != null) {
             holder = method.getDeclaringClass().getName();
             name = method.getName();
-            signature = method.getSignature().getMethodDescriptor();
+            signature = method.getSignature().toMethodDescriptor();
             startTime = System.nanoTime();
             bytecodeCount = method.getCodeSize();
             threadAllocatedBytesStart = getThreadAllocatedBytes();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Jul 15 19:21:28 2014 -0700
@@ -259,11 +259,11 @@
         } catch (BailoutException bailout) {
             BAILOUTS.increment();
             if (ExitVMOnBailout.getValue()) {
-                TTY.cachedOut.println(MetaUtil.format("Bailout in %H.%n(%p)", method));
+                TTY.cachedOut.println(method.format("Bailout in %H.%n(%p)"));
                 bailout.printStackTrace(TTY.cachedOut);
                 System.exit(-1);
             } else if (PrintBailout.getValue()) {
-                TTY.cachedOut.println(MetaUtil.format("Bailout in %H.%n(%p)", method));
+                TTY.cachedOut.println(method.format("Bailout in %H.%n(%p)"));
                 bailout.printStackTrace(TTY.cachedOut);
             }
         } catch (Throwable t) {
@@ -287,7 +287,7 @@
 
             // Log a compilation event.
             if (compilationEvent.shouldWrite()) {
-                compilationEvent.setMethod(MetaUtil.format("%H.%n(%p)", method));
+                compilationEvent.setMethod(method.format("%H.%n(%p)"));
                 compilationEvent.setCompileId(getId());
                 compilationEvent.setCompileLevel(config.compilationLevelFullOptimization);
                 compilationEvent.setSucceeded(true);
@@ -311,7 +311,7 @@
     }
 
     private String getMethodDescription() {
-        return String.format("%-6d Graal %-70s %-45s %-50s %s", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature().getMethodDescriptor(),
+        return String.format("%-6d Graal %-70s %-45s %-50s %s", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature().toMethodDescriptor(),
                         entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") ");
     }
 
@@ -328,7 +328,7 @@
 
     @Override
     public String toString() {
-        return "Compilation[id=" + id + ", " + MetaUtil.format("%H.%n(%p)", method) + (entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "@" + entryBCI) + "]";
+        return "Compilation[id=" + id + ", " + method.format("%H.%n(%p)") + (entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "@" + entryBCI) + "]";
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Tue Jul 15 19:21:28 2014 -0700
@@ -356,7 +356,7 @@
             method.reprofile();  // makes the method also not-entrant
         } catch (Throwable t) {
             // Catch everything and print a message
-            println("CompileTheWorld (%d) : Error compiling method: %s", classFileCounter, MetaUtil.format("%H.%n(%p):%r", method));
+            println("CompileTheWorld (%d) : Error compiling method: %s", classFileCounter, method.format("%H.%n(%p):%r"));
             t.printStackTrace(TTY.cachedOut);
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Jul 15 19:21:28 2014 -0700
@@ -370,32 +370,31 @@
     }
 
     /**
-     * Converts a name to a Java type.
+     * Converts a name to a Java type. This method attempts to resolve {@code name} to a
+     * {@link ResolvedJavaType}.
      *
      * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
-     * @param accessingType the context of resolution (may be null)
-     * @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
-     *            either return a {@link ResolvedJavaType} or throw an exception
+     * @param accessingType the context of resolution which must be non-null
+     * @param resolve specifies whether resolution failure results in an unresolved type being
+     *            return or a {@link LinkageError} being thrown
      * @return a Java type for {@code name} which is guaranteed to be of type
      *         {@link ResolvedJavaType} if {@code resolve == true}
      * @throws LinkageError if {@code resolve == true} and the resolution failed
+     * @throws NullPointerException if {@code accessingClass} is {@code null}
      */
     public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
+        Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class");
         // If the name represents a primitive type we can short-circuit the lookup.
         if (name.length() == 1) {
             Kind kind = Kind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
             return HotSpotResolvedPrimitiveType.fromKind(kind);
         }
 
-        // Handle non-primitive types.
-        Class<?> accessingClass = null;
-        if (accessingType != null) {
-            accessingClass = accessingType.mirror();
-        }
+        // Resolve non-primitive types in the VM.
+        final long metaspaceKlass = compilerToVm.lookupType(name, accessingType.mirror(), resolve);
 
-        // Resolve the type in the VM.
-        final long metaspaceKlass = compilerToVm.lookupType(name, accessingClass, resolve);
-        if (metaspaceKlass == 0) {
+        if (metaspaceKlass == 0L) {
+            assert resolve == false;
             return HotSpotUnresolvedJavaType.create(name);
         }
         return HotSpotResolvedObjectType.fromMetaspaceKlass(metaspaceKlass);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Tue Jul 15 19:21:28 2014 -0700
@@ -109,7 +109,7 @@
      * Converts a name to a metaspace klass.
      *
      * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
-     * @param accessingClass the context of resolution (may be null)
+     * @param accessingClass the context of resolution (must not be null)
      * @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
      *            either return a {@link ResolvedJavaType} or throw an exception
      * @return a metaspace klass for {@code name}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Tue Jul 15 19:21:28 2014 -0700
@@ -115,7 +115,7 @@
         String group = counter.getGroup();
         if (counter.isWithContext()) {
             StructuredGraph graph = counter.graph();
-            name = counter.getName() + " @ " + graph.graphId() + ":" + (graph.method() == null ? "" : MetaUtil.format("%h.%n", graph.method()));
+            name = counter.getName() + " @ " + graph.graphId() + ":" + (graph.method() == null ? "" : graph.method().format("%h.%n"));
             if (graph.name != null) {
                 name += " (" + graph.name + ")";
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/LocalImpl.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/LocalImpl.java	Tue Jul 15 19:21:28 2014 -0700
@@ -84,6 +84,6 @@
 
     @Override
     public String toString() {
-        return "LocalImpl<name=" + name + ", resolvedType=" + type + ", startBci=" + startBci + ", endBci=" + endBci + ", slot=" + slot + ">";
+        return "LocalImpl<name=" + name + ", type=" + type + ", startBci=" + startBci + ", endBci=" + endBci + ", slot=" + slot + ">";
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Tue Jul 15 19:21:28 2014 -0700
@@ -183,7 +183,7 @@
                 receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool);
                 invoke.setGuard(receiverNullCheck);
             }
-            JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
+            JavaType[] signature = callTarget.targetMethod().getSignature().toParameterTypes(callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
 
             LoweredCallTargetNode loweredCallTarget = null;
             boolean isVirtualOrInterface = callTarget.invokeKind() == InvokeKind.Virtual || callTarget.invokeKind() == InvokeKind.Interface;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.debug.Debug.*;
 import static java.util.FormattableFlags.*;
 
@@ -56,7 +55,7 @@
         char h = FULLY_QUALIFIED_METHOD_NAME ? 'H' : 'h';
         String suffix = this instanceof ResolvedJavaMethod ? "" : ", unresolved";
         String fmt = String.format("HotSpotMethod<%%%c.%%n(%%p)%s>", h, suffix);
-        return format(fmt, this);
+        return format(fmt);
     }
 
     public void formatTo(Formatter formatter, int flags, int width, int precision) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Tue Jul 15 19:21:28 2014 -0700
@@ -84,7 +84,7 @@
     /**
      * Returns the size of the extra data records. This method does the same calculation as
      * MethodData::extra_data_size().
-     * 
+     *
      * @return size of extra data records
      */
     private int extraDataSize() {
@@ -543,7 +543,7 @@
                             getTypesNotRecordedExecutionCount(data, pos), profile.entries));
             for (int i = 0; i < profile.entries; i++) {
                 long count = profile.counts[i];
-                sb.append(format("%n  %s (%d, %4.2f)", MetaUtil.toJavaName(profile.items[i]), count, (double) count / profile.totalCount));
+                sb.append(format("%n  %s (%d, %4.2f)", profile.items[i].toJavaName(), count, (double) count / profile.totalCount));
             }
             return sb;
         }
@@ -664,7 +664,7 @@
             super.appendTo(sb.append(format("exception_seen(%s) ", getExceptionSeen(data, pos))), data, pos).append(format("%nmethod_entries(%d)", profile.entries));
             for (int i = 0; i < profile.entries; i++) {
                 long count = profile.counts[i];
-                sb.append(format("%n  %s (%d, %4.2f)", MetaUtil.format("%H.%n(%p)", profile.items[i]), count, (double) count / profile.totalCount));
+                sb.append(format("%n  %s (%d, %4.2f)", profile.items[i].format("%H.%n(%p)"), count, (double) count / profile.totalCount));
             }
             return sb;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Tue Jul 15 19:21:28 2014 -0700
@@ -89,14 +89,14 @@
     }
 
     private boolean checkArgs(Object... args) {
-        JavaType[] sig = MetaUtil.signatureToTypes(method);
-        assert args.length == sig.length : MetaUtil.format("%H.%n(%p): expected ", method) + sig.length + " args, got " + args.length;
+        JavaType[] sig = method.toParameterTypes();
+        assert args.length == sig.length : method.format("%H.%n(%p): expected ") + sig.length + " args, got " + args.length;
         for (int i = 0; i < sig.length; i++) {
             Object arg = args[i];
             if (arg == null) {
-                assert sig[i].getKind() == Kind.Object : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be Object, not " + sig[i];
+                assert sig[i].getKind() == Kind.Object : method.format("%H.%n(%p): expected arg ") + i + " to be Object, not " + sig[i];
             } else if (sig[i].getKind() != Kind.Object) {
-                assert sig[i].getKind().toBoxedJavaClass() == arg.getClass() : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be " + sig[i] + ", not " + arg.getClass();
+                assert sig[i].getKind().toBoxedJavaClass() == arg.getClass() : method.format("%H.%n(%p): expected arg ") + i + " to be " + sig[i] + ", not " + arg.getClass();
             }
         }
         return true;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java	Tue Jul 15 19:21:28 2014 -0700
@@ -199,7 +199,7 @@
 
     @Override
     public String toString() {
-        return "HotSpotProfilingInfo<" + MetaUtil.profileToString(this, null, "; ") + ">";
+        return "HotSpotProfilingInfo<" + this.toString(null, "; ") + ">";
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType.*;
@@ -325,7 +324,7 @@
 
     @Override
     public String toString() {
-        return format("HotSpotField<%H.%n %t:", this) + offset + ">";
+        return format("HotSpotField<%H.%n %t:") + offset + ">";
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Tue Jul 15 19:21:28 2014 -0700
@@ -423,8 +423,8 @@
             long metaspaceMethodData = unsafeReadWord(metaspaceMethod + runtime().getConfig().methodDataOffset);
             if (metaspaceMethodData != 0) {
                 methodData = new HotSpotMethodData(metaspaceMethodData);
-                if (TraceMethodDataFilter != null && MetaUtil.format("%H.%n", this).contains(TraceMethodDataFilter)) {
-                    TTY.println("Raw method data for " + MetaUtil.format("%H.%n(%p)", this) + ":");
+                if (TraceMethodDataFilter != null && this.format("%H.%n").contains(TraceMethodDataFilter)) {
+                    TTY.println("Raw method data for " + this.format("%H.%n(%p)") + ":");
                     TTY.println(methodData.toString());
                 }
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static java.util.Objects.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
@@ -140,7 +140,7 @@
     public ResolvedJavaType findUniqueConcreteSubtype() {
         HotSpotVMConfig config = runtime().getConfig();
         if (isArray()) {
-            return getElementalType(this).isFinal() ? this : null;
+            return getElementalType().isFinal() ? this : null;
         } else if (isInterface()) {
             final long implementorMetaspaceKlass = runtime().getCompilerToVM().getKlassImplementor(getMetaspaceKlass());
 
@@ -349,6 +349,11 @@
     }
 
     @Override
+    public boolean isJavaLangObject() {
+        return javaClass.equals(Object.class);
+    }
+
+    @Override
     public Kind getKind() {
         return Kind.Object;
     }
@@ -706,9 +711,38 @@
         return mirror().getAnnotation(annotationClass);
     }
 
+    /**
+     * Determines if this type is resolved in the context of a given accessing class. This is a
+     * conservative check based on this type's class loader being identical to
+     * {@code accessingClass}'s loader. This type may still be the correct resolved type in the
+     * context of {@code accessingClass} if its loader is an ancestor of {@code accessingClass}'s
+     * loader.
+     */
+    public boolean isResolvedWithRespectTo(ResolvedJavaType accessingClass) {
+        assert accessingClass != null;
+        ResolvedJavaType elementType = getElementalType();
+        if (elementType.isPrimitive()) {
+            // Primitive type resolution is context free.
+            return true;
+        }
+        if (elementType.getName().startsWith("Ljava/")) {
+            // Classes in a java.* package can only be defined by the
+            // boot class loader. This is enforced by ClassLoader.preDefineClass()
+            assert mirror().getClassLoader() == null;
+            return true;
+        }
+        ClassLoader thisCl = mirror().getClassLoader();
+        ClassLoader accessingClassCl = ((HotSpotResolvedObjectType) accessingClass).mirror().getClassLoader();
+        return thisCl == accessingClassCl;
+    }
+
     @Override
     public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
-        return this;
+        if (isResolvedWithRespectTo(requireNonNull(accessingClass))) {
+            return this;
+        }
+        HotSpotResolvedObjectType accessingType = (HotSpotResolvedObjectType) accessingClass;
+        return (ResolvedJavaType) runtime().lookupType(getName(), accessingType, true);
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static java.util.Objects.*;
+
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.net.*;
@@ -77,6 +79,10 @@
         return HotSpotResolvedObjectType.fromClass(javaArrayMirror);
     }
 
+    public ResolvedJavaType getElementalType() {
+        return this;
+    }
+
     @Override
     public ResolvedJavaType getComponentType() {
         return null;
@@ -163,6 +169,11 @@
     }
 
     @Override
+    public boolean isJavaLangObject() {
+        return false;
+    }
+
+    @Override
     public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
         return null;
     }
@@ -199,6 +210,7 @@
 
     @Override
     public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
+        requireNonNull(accessingClass);
         return this;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java	Tue Jul 15 19:21:28 2014 -0700
@@ -40,8 +40,8 @@
     private final List<String> parameters = new ArrayList<>();
     private final String returnType;
     private final String originalString;
-    private JavaType[] parameterTypes;
-    private JavaType returnTypeCache;
+    private ResolvedJavaType[] parameterTypes;
+    private ResolvedJavaType returnTypeCache;
 
     public HotSpotSignature(String signature) {
         assert signature.length() > 0;
@@ -64,7 +64,7 @@
         }
     }
 
-    public HotSpotSignature(JavaType returnType, JavaType... parameterTypes) {
+    public HotSpotSignature(ResolvedJavaType returnType, ResolvedJavaType... parameterTypes) {
         this.parameterTypes = parameterTypes.clone();
         this.returnTypeCache = returnType;
         this.returnType = returnType.getName();
@@ -128,37 +128,47 @@
     }
 
     private static boolean checkValidCache(JavaType type, ResolvedJavaType accessingClass) {
+        assert accessingClass != null;
         if (!(type instanceof ResolvedJavaType)) {
             return false;
         }
 
         if (type instanceof HotSpotResolvedObjectType) {
-            HotSpotResolvedObjectType resolved = (HotSpotResolvedObjectType) type;
-            if (accessingClass == null) {
-                return resolved.mirror().getClassLoader() == null;
-            } else {
-                return resolved.mirror().getClassLoader() == ((HotSpotResolvedObjectType) accessingClass).mirror().getClassLoader();
-            }
+            return ((HotSpotResolvedObjectType) type).isResolvedWithRespectTo(accessingClass);
         }
+        return true;
+    }
 
-        return true;
+    private static JavaType getUnresolvedOrPrimitiveType(String name) {
+        if (name.length() == 1) {
+            Kind kind = Kind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
+            return HotSpotResolvedPrimitiveType.fromKind(kind);
+        }
+        return new HotSpotUnresolvedJavaType(name);
     }
 
     @Override
     public JavaType getParameterType(int index, ResolvedJavaType accessingClass) {
-        if (parameterTypes == null) {
-            parameterTypes = new JavaType[parameters.size()];
+        if (accessingClass == null) {
+            // Caller doesn't care about resolution context so return an unresolved
+            // or primitive type (primitive type resolution is context free)
+            return getUnresolvedOrPrimitiveType(parameters.get(index));
         }
-        JavaType type = parameterTypes[index];
+        if (parameterTypes == null) {
+            parameterTypes = new ResolvedJavaType[parameters.size()];
+        }
+
+        ResolvedJavaType type = parameterTypes[index];
         if (!checkValidCache(type, accessingClass)) {
-            type = runtime().lookupType(parameters.get(index), (HotSpotResolvedObjectType) accessingClass, false);
+            type = (ResolvedJavaType) runtime().lookupType(parameters.get(index), (HotSpotResolvedObjectType) accessingClass, true);
             parameterTypes[index] = type;
         }
         return type;
     }
 
-    public String getMethodDescriptor() {
-        assert originalString.equals(MetaUtil.signatureToMethodDescriptor(this));
+    @Override
+    public String toMethodDescriptor() {
+        assert originalString.equals(Signature.super.toMethodDescriptor());
         return originalString;
     }
 
@@ -169,8 +179,13 @@
 
     @Override
     public JavaType getReturnType(ResolvedJavaType accessingClass) {
+        if (accessingClass == null) {
+            // Caller doesn't care about resolution context so return an unresolved
+            // or primitive type (primitive type resolution is context free)
+            return getUnresolvedOrPrimitiveType(returnType);
+        }
         if (!checkValidCache(returnTypeCache, accessingClass)) {
-            returnTypeCache = runtime().lookupType(returnType, (HotSpotResolvedObjectType) accessingClass, false);
+            returnTypeCache = (ResolvedJavaType) runtime().lookupType(returnType, (HotSpotResolvedObjectType) accessingClass, true);
         }
         return returnTypeCache;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 import com.oracle.graal.api.meta.*;
 
 /**
@@ -79,6 +77,6 @@
      */
     @Override
     public String toString() {
-        return format("HotSpotField<%H.%n %t, unresolved>", this);
+        return format("HotSpotField<%H.%n %t, unresolved>");
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedJavaType.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedJavaType.java	Tue Jul 15 19:21:28 2014 -0700
@@ -35,13 +35,13 @@
 
     public HotSpotUnresolvedJavaType(String name) {
         super(name);
+        assert name.charAt(0) == '[' || name.charAt(name.length() - 1) == ';' : name;
     }
 
     /**
      * Creates an unresolved type for a valid {@link JavaType#getName() type name}.
      */
     public static HotSpotUnresolvedJavaType create(String name) {
-        assert name.charAt(name.length() - 1) == ';' : name;
         return new HotSpotUnresolvedJavaType(name);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -67,12 +67,4 @@
 
     @NodeIntrinsic
     public static native Word fetchUnrollInfo(long registerSaver);
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return null;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -96,12 +96,4 @@
      */
     @NodeIntrinsic
     public static native Word compareAndSwap(Object object, long offset, Word expectedValue, Word newValue, @ConstantNodeParameter LocationIdentity locationIdentity);
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,15 +24,18 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * Saves all allocatable registers.
  */
-public class SaveAllRegistersNode extends FixedWithNextNode implements LIRLowerable {
+@NodeInfo(allowedUsageTypes = {InputType.Memory})
+public class SaveAllRegistersNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single {
 
     private SaveRegistersOp saveRegistersOp;
 
@@ -59,4 +62,8 @@
      */
     @NodeIntrinsic
     public static native long saveAllRegisters();
+
+    public LocationIdentity getLocationIdentity() {
+        return LocationIdentity.ANY_LOCATION;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,10 +22,13 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -54,7 +57,10 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return foreignCalls.getKilledLocations(descriptor);
+        LocationIdentity[] killedLocations = foreignCalls.getKilledLocations(descriptor);
+        killedLocations = Arrays.copyOf(killedLocations, killedLocations.length + 1);
+        killedLocations[killedLocations.length - 1] = HotSpotReplacementsUtil.PENDING_EXCEPTION_LOCATION;
+        return killedLocations;
     }
 
     protected Value[] operands(NodeLIRBuilderTool gen) {
@@ -83,12 +89,4 @@
         }
         return super.toString(verbosity);
     }
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -63,7 +63,7 @@
         ResolvedJavaMethod method = frameState.method();
         boolean isStatic = method.isStatic();
 
-        JavaType[] signature = MetaUtil.signatureToTypes(method.getSignature(), isStatic ? null : method.getDeclaringClass());
+        JavaType[] signature = method.getSignature().toParameterTypes(isStatic ? null : method.getDeclaringClass());
         CallingConvention cc = lirGen.getResult().getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, lirGen.target(), false);
         List<ValueNode> parameters = new ArrayList<>();
         for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += HIRFrameStateBuilder.stackSlots(frameState.localAt(slot).getKind())) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -70,12 +70,4 @@
 
     @NodeIntrinsic
     public static native Word uncommonTrap(long registerSaver, int trapRequest);
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return null;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.hotspot.nodes.CStringNode.*;
 
@@ -62,7 +61,7 @@
             whereString = sb.toString();
         } else {
             ResolvedJavaMethod method = graph().method();
-            whereString = "in compiled code for " + (method == null ? graph().toString() : format("%H.%n(%p)", method));
+            whereString = "in compiled code for " + (method == null ? graph().toString() : method.format("%H.%n(%p)"));
         }
         Value whereArg = emitCString(gen, whereString);
         Value formatArg = emitCString(gen, format);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.HeapAccess.BarrierType;
@@ -90,74 +91,66 @@
 
     private void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) {
         BarrierType barrierType = node.getBarrierType();
-        if (barrierType == BarrierType.PRECISE) {
-            if (useG1GC()) {
-                if (!node.isInitialization()) {
-                    addG1PreWriteBarrier(node, node.object(), null, node.location(), true, node.getNullCheck(), graph);
+        switch (barrierType) {
+            case NONE:
+                // nothing to do
+                break;
+            case IMPRECISE:
+            case PRECISE:
+                boolean precise = barrierType == BarrierType.PRECISE;
+                if (useG1GC()) {
+                    if (!node.isInitialization()) {
+                        addG1PreWriteBarrier(node, node.object(), null, node.location(), true, node.getNullCheck(), graph);
+                    }
+                    addG1PostWriteBarrier(node, node.object(), node.value(), node.location(), precise, graph);
+                } else {
+                    addSerialPostWriteBarrier(node, node.object(), node.value(), node.location(), precise, graph);
                 }
-                addG1PostWriteBarrier(node, node.object(), node.value(), node.location(), true, graph);
-            } else {
-                addSerialPostWriteBarrier(node, node.object(), node.value(), node.location(), true, graph);
-            }
-        } else if (barrierType == BarrierType.IMPRECISE) {
-            if (useG1GC()) {
-                if (!node.isInitialization()) {
-                    addG1PreWriteBarrier(node, node.object(), null, node.location(), true, node.getNullCheck(), graph);
-                }
-                addG1PostWriteBarrier(node, node.object(), node.value(), node.location(), false, graph);
-            } else {
-                addSerialPostWriteBarrier(node, node.object(), node.value(), node.location(), false, graph);
-            }
-        } else {
-            assert barrierType == BarrierType.NONE;
+                break;
+            default:
+                throw new GraalInternalError("unexpected barrier type: " + barrierType);
         }
     }
 
-    private void addAtomicReadWriteNodeBarriers(LoweredAtomicReadAndWriteNode loweredAtomicReadAndWriteNode, StructuredGraph graph) {
-        BarrierType barrierType = loweredAtomicReadAndWriteNode.getBarrierType();
-        if (barrierType == BarrierType.PRECISE) {
-            if (useG1GC()) {
-                addG1PreWriteBarrier(loweredAtomicReadAndWriteNode, loweredAtomicReadAndWriteNode.object(), null, loweredAtomicReadAndWriteNode.location(), true,
-                                loweredAtomicReadAndWriteNode.getNullCheck(), graph);
-                addG1PostWriteBarrier(loweredAtomicReadAndWriteNode, loweredAtomicReadAndWriteNode.object(), loweredAtomicReadAndWriteNode.getNewValue(), loweredAtomicReadAndWriteNode.location(),
-                                true, graph);
-            } else {
-                addSerialPostWriteBarrier(loweredAtomicReadAndWriteNode, loweredAtomicReadAndWriteNode.object(), loweredAtomicReadAndWriteNode.getNewValue(), loweredAtomicReadAndWriteNode.location(),
-                                true, graph);
-            }
-        } else if (barrierType == BarrierType.IMPRECISE) {
-            if (useG1GC()) {
-                addG1PreWriteBarrier(loweredAtomicReadAndWriteNode, loweredAtomicReadAndWriteNode.object(), null, loweredAtomicReadAndWriteNode.location(), true,
-                                loweredAtomicReadAndWriteNode.getNullCheck(), graph);
-                addG1PostWriteBarrier(loweredAtomicReadAndWriteNode, loweredAtomicReadAndWriteNode.object(), loweredAtomicReadAndWriteNode.getNewValue(), loweredAtomicReadAndWriteNode.location(),
-                                false, graph);
-            } else {
-                addSerialPostWriteBarrier(loweredAtomicReadAndWriteNode, loweredAtomicReadAndWriteNode.object(), loweredAtomicReadAndWriteNode.getNewValue(), loweredAtomicReadAndWriteNode.location(),
-                                false, graph);
-            }
-        } else {
-            assert barrierType == BarrierType.NONE;
+    private void addAtomicReadWriteNodeBarriers(LoweredAtomicReadAndWriteNode node, StructuredGraph graph) {
+        BarrierType barrierType = node.getBarrierType();
+        switch (barrierType) {
+            case NONE:
+                // nothing to do
+                break;
+            case IMPRECISE:
+            case PRECISE:
+                boolean precise = barrierType == BarrierType.PRECISE;
+                if (useG1GC()) {
+                    addG1PreWriteBarrier(node, node.object(), null, node.location(), true, node.getNullCheck(), graph);
+                    addG1PostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), precise, graph);
+                } else {
+                    addSerialPostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), precise, graph);
+                }
+                break;
+            default:
+                throw new GraalInternalError("unexpected barrier type: " + barrierType);
         }
     }
 
     private void addCASBarriers(LoweredCompareAndSwapNode node, StructuredGraph graph) {
         BarrierType barrierType = node.getBarrierType();
-        if (barrierType == BarrierType.PRECISE) {
-            if (useG1GC()) {
-                addG1PreWriteBarrier(node, node.object(), node.getExpectedValue(), node.location(), false, false, graph);
-                addG1PostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), true, graph);
-            } else {
-                addSerialPostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), true, graph);
-            }
-        } else if (barrierType == BarrierType.IMPRECISE) {
-            if (useG1GC()) {
-                addG1PreWriteBarrier(node, node.object(), node.getExpectedValue(), node.location(), false, false, graph);
-                addG1PostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), false, graph);
-            } else {
-                addSerialPostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), false, graph);
-            }
-        } else {
-            assert barrierType == BarrierType.NONE;
+        switch (barrierType) {
+            case NONE:
+                // nothing to do
+                break;
+            case IMPRECISE:
+            case PRECISE:
+                boolean precise = barrierType == BarrierType.PRECISE;
+                if (useG1GC()) {
+                    addG1PreWriteBarrier(node, node.object(), node.getExpectedValue(), node.location(), false, false, graph);
+                    addG1PostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), precise, graph);
+                } else {
+                    addSerialPostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), precise, graph);
+                }
+                break;
+            default:
+                throw new GraalInternalError("unexpected barrier type: " + barrierType);
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AssertionSnippets.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AssertionSnippets.java	Tue Jul 15 19:21:28 2014 -0700
@@ -67,9 +67,6 @@
     @NodeIntrinsic(ForeignCallNode.class)
     private static native void vmMessageC(@ConstantNodeParameter ForeignCallDescriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3);
 
-    @NodeIntrinsic(StubForeignCallNode.class)
-    private static native void stubVmMessageC(@ConstantNodeParameter ForeignCallDescriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3);
-
     public static class Templates extends AbstractTemplates {
 
         private final SnippetInfo assertion = snippet(AssertionSnippets.class, "assertion");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Tue Jul 15 19:21:28 2014 -0700
@@ -481,7 +481,7 @@
                 if (method == null) {
                     return false;
                 }
-                return (MetaUtil.format("%H.%n", method).contains(TRACE_METHOD_FILTER));
+                return (method.format("%H.%n").contains(TRACE_METHOD_FILTER));
             }
         }
 
@@ -506,7 +506,7 @@
                     List<ReturnNode> rets = graph.getNodes(ReturnNode.class).snapshot();
                     for (ReturnNode ret : rets) {
                         returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass());
-                        String msg = "unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d";
+                        String msg = "unbalanced monitors in " + graph.method().format("%H.%n(%p)") + ", count = %d";
                         ConstantNode errMsg = ConstantNode.forConstant(HotSpotObjectConstant.forObject(msg), providers.getMetaAccess(), graph);
                         callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType));
                         invoke = graph.add(new InvokeNode(callTarget, 0));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Tue Jul 15 19:21:28 2014 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.api.code.UnsignedMath.*;
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.Options.*;
@@ -398,7 +397,7 @@
             args.addConst("fillContents", newInstanceNode.fillContents());
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("constantSize", true);
-            args.addConst("typeContext", ProfileAllocations.getValue() ? toJavaName(type, false) : "");
+            args.addConst("typeContext", ProfileAllocations.getValue() ? type.toJavaName(false) : "");
 
             SnippetTemplate template = template(args);
             Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args);
@@ -428,7 +427,7 @@
             args.addConst("fillContents", newArrayNode.fillContents());
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("maybeUnroll", length.isConstant());
-            args.addConst("typeContext", ProfileAllocations.getValue() ? toJavaName(arrayType, false) : "");
+            args.addConst("typeContext", ProfileAllocations.getValue() ? arrayType.toJavaName(false) : "");
 
             SnippetTemplate template = template(args);
             Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java	Tue Jul 15 19:21:28 2014 -0700
@@ -135,7 +135,7 @@
          * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for
          * total size of the interpreter frames plus shadow page size. Bang one page at a time
          * because large sizes can bang beyond yellow and red zones.
-         *
+         * 
          * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository.
          */
         final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset());
@@ -143,7 +143,7 @@
         Word stackPointer = readRegister(stackPointerRegister);
 
         for (int i = 1; i < bangPages; i++) {
-            stackPointer.writeInt((-i * pageSize()) + stackBias(), 0);
+            stackPointer.writeInt((-i * pageSize()) + stackBias(), 0, UncommonTrapStub.STACK_BANG_LOCATION);
         }
 
         // Load number of interpreter frames.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Tue Jul 15 19:21:28 2014 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.stubs;
 
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 
 import com.oracle.graal.api.meta.*;
@@ -115,7 +114,7 @@
                 ForeignCallDescriptor d = linkage.getDescriptor();
                 MetaAccessProvider metaAccess = providers.getMetaAccess();
                 Class<?>[] arguments = d.getArgumentTypes();
-                JavaType[] parameters = new JavaType[arguments.length];
+                ResolvedJavaType[] parameters = new ResolvedJavaType[arguments.length];
                 for (int i = 0; i < arguments.length; i++) {
                     parameters[i] = metaAccess.lookupJavaType(arguments[i]);
                 }
@@ -132,7 +131,7 @@
 
             @Override
             public String toString() {
-                return format("ForeignCallStub<%n(%p)>", this);
+                return format("ForeignCallStub<%n(%p)>");
             }
         };
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
@@ -125,6 +123,6 @@
 
     @Override
     public String toString() {
-        return "Stub<" + format("%h.%n", getInstalledCodeOwner()) + ">";
+        return "Stub<" + getInstalledCodeOwner().format("%h.%n") + ">";
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Tue Jul 15 19:21:28 2014 -0700
@@ -43,6 +43,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
 
 //JaCoCo Exclude
 
@@ -160,8 +161,10 @@
                 compResult = new CompilationResult(toString());
                 try (Scope s0 = Debug.scope("StubCompilation", graph, providers.getCodeCache())) {
                     Assumptions assumptions = new Assumptions(OptAssumptions.getValue());
+                    Suites defaultSuites = providers.getSuites().getDefaultSuites();
+                    Suites suites = new Suites(new PhaseSuite<>(), defaultSuites.getMidTier(), defaultSuites.getLowTier());
                     SchedulePhase schedule = emitFrontEnd(providers, target, graph, assumptions, null, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL,
-                                    getProfilingInfo(graph), null, providers.getSuites().getDefaultSuites());
+                                    getProfilingInfo(graph), null, suites);
                     emitBackEnd(graph, Stub.this, incomingCc, getInstalledCodeOwner(), backend, target, compResult, CompilationResultBuilderFactory.Default, assumptions, schedule, getRegisterConfig());
                 } catch (Throwable e) {
                     throw Debug.handle(e);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java	Tue Jul 15 19:21:28 2014 -0700
@@ -77,6 +77,8 @@
  */
 public class UncommonTrapStub extends SnippetStub {
 
+    public static final LocationIdentity STACK_BANG_LOCATION = new NamedLocationIdentity("stack bang");
+
     private final TargetDescription target;
 
     public UncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) {
@@ -152,7 +154,7 @@
         Word stackPointer = readRegister(stackPointerRegister);
 
         for (int i = 1; i < bangPages; i++) {
-            stackPointer.writeInt((-i * pageSize()) + stackBias(), 0);
+            stackPointer.writeInt((-i * pageSize()) + stackBias(), 0, STACK_BANG_LOCATION);
         }
 
         // Load number of interpreter frames.
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Tue Jul 15 19:21:28 2014 -0700
@@ -246,6 +246,10 @@
         public double probability() {
             return 1D;
         }
+
+        public BciBlock getPostdominator() {
+            return null;
+        }
     }
 
     public static class ExceptionDispatchBlock extends BciBlock {
@@ -1058,7 +1062,7 @@
         BciBlockMapping map = new BciBlockMapping(method);
         map.build();
         if (Debug.isDumpEnabled()) {
-            Debug.dump(map, MetaUtil.format("After block building %f %R %H.%n(%P)", method));
+            Debug.dump(map, method.format("After block building %f %R %H.%n(%P)"));
         }
 
         return map;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Tue Jul 15 19:21:28 2014 -0700
@@ -47,7 +47,7 @@
 
     /**
      * Disassembles the bytecode of a given method in a {@code javap}-like format.
-     * 
+     *
      * @return {@code null} if {@code method} has no bytecode (e.g., it is native or abstract)
      */
     public String disassemble(ResolvedJavaMethod method) {
@@ -73,7 +73,7 @@
                     case ANEWARRAY      : {
                         int cpi = stream.readCPI();
                         JavaType type = cp.lookupType(cpi, opcode);
-                        buf.append(String.format("#%-10d // %s", cpi, MetaUtil.toJavaName(type)));
+                        buf.append(String.format("#%-10d // %s", cpi, type.toJavaName()));
                         break;
                     }
                     case GETSTATIC      :
@@ -82,7 +82,7 @@
                     case PUTFIELD       : {
                         int cpi = stream.readCPI();
                         JavaField field = cp.lookupField(cpi, opcode);
-                        String fieldDesc = field.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? MetaUtil.format("%n:%T", field) : MetaUtil.format("%H.%n:%T", field);
+                        String fieldDesc = field.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? field.format("%n:%T") : field.format("%H.%n:%T");
                         buf.append(String.format("#%-10d // %s", cpi, fieldDesc));
                         break;
                     }
@@ -91,21 +91,21 @@
                     case INVOKESTATIC   : {
                         int cpi = stream.readCPI();
                         JavaMethod callee = cp.lookupMethod(cpi, opcode);
-                        String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee);
+                        String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? callee.format("%n:(%P)%R") : callee.format("%H.%n:(%P)%R");
                         buf.append(String.format("#%-10d // %s", cpi, calleeDesc));
                         break;
                     }
                     case INVOKEINTERFACE: {
                         int cpi = stream.readCPI();
                         JavaMethod callee = cp.lookupMethod(cpi, opcode);
-                        String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee);
+                        String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? callee.format("%n:(%P)%R") : callee.format("%H.%n:(%P)%R");
                         buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), calleeDesc));
                         break;
                     }
                     case INVOKEDYNAMIC: {
                         int cpi = stream.readCPI4();
                         JavaMethod callee = cp.lookupMethod(cpi, opcode);
-                        String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee);
+                        String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? callee.format("%n:(%P)%R") : callee.format("%H.%n:(%P)%R");
                         buf.append(String.format("#%-10d // %s", cpi, calleeDesc));
                         break;
                     }
@@ -206,7 +206,7 @@
                     case MULTIANEWARRAY : {
                         int cpi = stream.readCPI();
                         JavaType type = cp.lookupType(cpi, opcode);
-                        buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), MetaUtil.toJavaName(type)));
+                        buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), type.toJavaName()));
                         break;
                     }
                 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Jul 15 19:21:28 2014 -0700
@@ -171,7 +171,7 @@
 
         @Override
         protected String getDetailedName() {
-            return getName() + " " + MetaUtil.format("%H.%n(%p):%r", parser.getMethod());
+            return getName() + " " + parser.getMethod().format("%H.%n(%p):%r");
         }
 
         public static class ExceptionInfo {
@@ -213,8 +213,8 @@
             @Override
             protected void build() {
                 if (PrintProfilingInformation.getValue()) {
-                    TTY.println("Profiling info for " + MetaUtil.format("%H.%n(%p)", method));
-                    TTY.println(MetaUtil.indent(MetaUtil.profileToString(profilingInfo, method, CodeUtil.NEW_LINE), "  "));
+                    TTY.println("Profiling info for " + method.format("%H.%n(%p)"));
+                    TTY.println(MetaUtil.indent(profilingInfo.toString(method, CodeUtil.NEW_LINE), "  "));
                 }
 
                 try (Indent indent = Debug.logAndIndent("build graph for %s", method)) {
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.jtt;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static java.lang.reflect.Modifier.*;
 
 import java.lang.reflect.*;
@@ -63,7 +62,7 @@
         if (argsToBind != null) {
             Object receiver = isStatic(m.getModifiers()) ? null : this;
             Object[] args = argsWithReceiver(receiver, argsToBind);
-            JavaType[] parameterTypes = signatureToTypes(getMetaAccess().lookupJavaMethod(m));
+            JavaType[] parameterTypes = getMetaAccess().lookupJavaMethod(m).toParameterTypes();
             assert parameterTypes.length == args.length;
             for (int i = 0; i < args.length; i++) {
                 ParameterNode param = graph.getParameter(i);
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java	Tue Jul 15 19:21:28 2014 -0700
@@ -51,7 +51,7 @@
         AbstractEndNode forwardEnd = loopBegin.forwardEnd();
         for (PhiNode phi : loopBegin.phis()) {
             ValueNode backValue = phi.singleBackValue();
-            if (backValue == null) {
+            if (backValue == PhiNode.NO_VALUE) {
                 continue;
             }
             ValueNode stride = addSub(backValue, phi);
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.cfg.*;
@@ -145,7 +144,7 @@
             BinaryNode result = BinaryNode.reassociate(binary, invariant, binary.getX(), binary.getY());
             if (result != binary) {
                 if (Debug.isLogEnabled()) {
-                    Debug.log("%s : Reassociated %s into %s", MetaUtil.format("%H::%n", graph.method()), binary, result);
+                    Debug.log("%s : Reassociated %s into %s", graph.method().format("%H::%n"), binary, result);
                 }
                 if (!result.isAlive()) {
                     assert !result.isDeleted();
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Tue Jul 15 19:21:28 2014 -0700
@@ -332,7 +332,7 @@
                  * VirtualState nodes contained in the old exit's state may be shared by other
                  * dominated VirtualStates. Those dominated virtual states need to see the
                  * proxy->phi update that are applied below.
-                 * 
+                 *
                  * We now update the original fragment's nodes accordingly:
                  */
                 originalExitState.applyToVirtual(node -> original.nodes.clearAndGrow(node));
@@ -357,8 +357,6 @@
                         phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(), merge));
                     } else if (vpn instanceof GuardProxyNode) {
                         phi = graph.addWithoutUnique(new GuardPhiNode(merge));
-                    } else if (vpn instanceof MemoryProxyNode) {
-                        phi = graph.addWithoutUnique(new MemoryPhiNode(merge, ((MemoryProxyNode) vpn).getLocationIdentity()));
                     } else {
                         throw GraalInternalError.shouldNotReachHere();
                     }
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Tue Jul 15 19:21:28 2014 -0700
@@ -299,4 +299,16 @@
         assertFalse(new IntegerStamp(32, 0, 0xff00, 0, 0xff00).join(new IntegerStamp(32, 1, 0xff, 0x00, 0xff)).isLegal());
         assertFalse(new IntegerStamp(32, 0x100, 0xff00, 0, 0xff00).join(new IntegerStamp(32, 0, 0xff, 0x00, 0xff)).isLegal());
     }
+
+    @Test
+    public void testShiftLeft() {
+        assertEquals(new IntegerStamp(32, 0, 0x1ff, 0, 0x1ff), StampTool.leftShift(new IntegerStamp(32, 0, 0xff, 0, 0xff), new IntegerStamp(32, 0, 1, 0, 1)));
+        assertEquals(new IntegerStamp(32, 0, 0x1fe0, 0, 0x1fe0), StampTool.leftShift(new IntegerStamp(32, 0, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5)));
+        assertEquals(new IntegerStamp(32, 0x1e0, 0x1fe0, 0, 0x1fe0), StampTool.leftShift(new IntegerStamp(32, 0xf, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5)));
+
+        assertEquals(new IntegerStamp(64, 0, 0x1ff, 0, 0x1ff), StampTool.leftShift(new IntegerStamp(64, 0, 0xff, 0, 0xff), new IntegerStamp(32, 0, 1, 0, 1)));
+        assertEquals(new IntegerStamp(64, 0, 0x1fe0, 0, 0x1fe0), StampTool.leftShift(new IntegerStamp(64, 0, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5)));
+        assertEquals(new IntegerStamp(64, 0x1e0, 0x1fe0, 0, 0x1fe0), StampTool.leftShift(new IntegerStamp(64, 0xf, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5)));
+
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java	Tue Jul 15 19:21:28 2014 -0700
@@ -37,12 +37,4 @@
     protected AbstractMemoryCheckpoint(Stamp stamp, FrameState stateAfter) {
         super(stamp, stateAfter);
     }
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -36,6 +36,6 @@
 
     @Override
     public String targetName() {
-        return MetaUtil.format("Direct#%h.%n", target());
+        return target().format("Direct#%h.%n");
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -26,6 +26,9 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 
+/**
+ * Guard {@link PhiNode}s merge guard dependencies at control flow merges.
+ */
 @NodeInfo(nameTemplate = "GuardPhi({i#values})", allowedUsageTypes = {InputType.Guard})
 public class GuardPhiNode extends PhiNode implements GuardingNode {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -224,9 +224,7 @@
                     if (nodeClass.inputsEqual(trueNext, falseNext) && nodeClass.valueEqual(trueNext, falseNext)) {
                         falseNext.replaceAtUsages(trueNext);
                         graph().removeFixed(falseNext);
-                        FixedNode next = trueNext.next();
-                        trueNext.setNext(null);
-                        trueNext.replaceAtPredecessor(next);
+                        GraphUtil.unlinkFixedNode(trueNext);
                         graph().addBeforeFixed(this, trueNext);
                         for (Node usage : trueNext.usages().snapshot()) {
                             if (usage.isAlive()) {
@@ -246,7 +244,8 @@
                     }
                 }
             }
-        } while (false);
+            break;
+        } while (true);
     }
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -43,6 +43,6 @@
 
     @Override
     public String targetName() {
-        return MetaUtil.format("Indirect#%h.%n", target());
+        return target().format("Indirect#%h.%n");
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -232,12 +232,4 @@
         updateUsagesInterface(this.guard, guard);
         this.guard = guard;
     }
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -48,12 +48,4 @@
     public LocationIdentity getLocationIdentity() {
         return locationIdentity;
     }
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -28,7 +28,7 @@
 import com.oracle.graal.nodes.extended.*;
 
 /**
- * The {@code PhiNode} represents the merging of dataflow in the memory graph.
+ * Memory {@code PhiNode}s merge memory dependencies at control flow merges.
  */
 @NodeInfo(nameTemplate = "MemoryPhi({i#values}) {p#locationIdentity/s}", allowedUsageTypes = {InputType.Memory})
 public class MemoryPhiNode extends PhiNode implements MemoryNode {
@@ -45,14 +45,6 @@
         return locationIdentity;
     }
 
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return null;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return this;
-    }
-
     @Override
     public NodeInputList<ValueNode> values() {
         return values;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, 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;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-
-@NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class MemoryProxyNode extends ProxyNode implements MemoryProxy, LIRLowerable {
-
-    @Input(InputType.Memory) private MemoryNode value;
-    private final LocationIdentity identity;
-
-    public MemoryProxyNode(MemoryNode value, BeginNode exit, LocationIdentity identity) {
-        super(StampFactory.forVoid(), exit);
-        this.value = value;
-        this.identity = identity;
-    }
-
-    @Override
-    public ValueNode value() {
-        return value.asNode();
-    }
-
-    public LocationIdentity getLocationIdentity() {
-        return identity;
-    }
-
-    @Override
-    public void generate(NodeLIRBuilderTool generator) {
-    }
-
-    @Override
-    public boolean verify() {
-        assert value() instanceof MemoryNode : this + " " + value();
-        return super.verify();
-    }
-
-    public MemoryNode getOriginalMemoryNode() {
-        return (MemoryNode) value();
-    }
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return getOriginalMemoryNode().asMemoryCheckpoint();
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return getOriginalMemoryNode().asMemoryPhi();
-    }
-
-    public Node getOriginalNode() {
-        return value.asNode();
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,12 +22,20 @@
  */
 package com.oracle.graal.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.calc.*;
 
-public abstract class PhiNode extends FloatingNode {
+/**
+ * {@code PhiNode}s represent the merging of edges at a control flow merges ({@link MergeNode} or
+ * {@link LoopBeginNode}). For a {@link MergeNode}, the order of the values corresponds to the order
+ * of the ends. For {@link LoopBeginNode}s, the first value corresponds to the loop's predecessor,
+ * while the rest of the values correspond to the {@link LoopEndNode}s.
+ */
+public abstract class PhiNode extends FloatingNode implements Simplifiable {
 
     @Input(InputType.Association) private MergeNode merge;
 
@@ -129,39 +137,42 @@
         values().remove(index);
     }
 
+    public static final ValueNode NO_VALUE = new ValueNode(null) {
+        // empty dummy class
+    };
+
     public ValueNode singleValue() {
-        ValueNode differentValue = null;
-        for (ValueNode n : values()) {
-            assert n != null : "Must have input value!";
-            if (n != this) {
-                if (differentValue == null) {
-                    differentValue = n;
-                } else if (differentValue != n) {
-                    return null;
+        Iterator<ValueNode> iterator = values().iterator();
+        ValueNode singleValue = iterator.next();
+        while (iterator.hasNext()) {
+            ValueNode value = iterator.next();
+            if (value != this) {
+                if (value != singleValue) {
+                    return NO_VALUE;
                 }
             }
         }
-        return differentValue;
+        return singleValue;
     }
 
     public ValueNode singleBackValue() {
         assert merge() instanceof LoopBeginNode;
-        ValueNode differentValue = null;
-        for (ValueNode n : values().subList(merge().forwardEndCount(), values().size())) {
-            if (differentValue == null) {
-                differentValue = n;
-            } else if (differentValue != n) {
-                return null;
+        Iterator<ValueNode> iterator = values().iterator();
+        iterator.next();
+        ValueNode singleValue = iterator.next();
+        while (iterator.hasNext()) {
+            if (iterator.next() != singleValue) {
+                return NO_VALUE;
             }
         }
-        return differentValue;
+        return singleValue;
     }
 
     @Override
     public void simplify(SimplifierTool tool) {
         ValueNode singleValue = singleValue();
 
-        if (singleValue != null) {
+        if (singleValue != NO_VALUE) {
             for (Node node : usages().snapshot()) {
                 if (node instanceof ProxyNode && ((ProxyNode) node).proxyPoint() instanceof LoopExitNode && ((LoopExitNode) ((ProxyNode) node).proxyPoint()).loopBegin() == merge) {
                     tool.addToWorkList(node.usages());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
@@ -57,10 +56,6 @@
         return super.verify();
     }
 
-    public static MemoryProxyNode forMemory(MemoryNode value, BeginNode exit, LocationIdentity location, StructuredGraph graph) {
-        return graph.unique(new MemoryProxyNode(value, exit, location));
-    }
-
     public static ValueProxyNode forValue(ValueNode value, BeginNode exit, StructuredGraph graph) {
         return graph.unique(new ValueProxyNode(value, exit));
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -36,12 +36,4 @@
     public LocationIdentity getLocationIdentity() {
         return LocationIdentity.ANY_LOCATION;
     }
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Jul 15 19:21:28 2014 -0700
@@ -259,9 +259,7 @@
             ((BeginNode) node).prepareDelete();
         }
         assert node.usages().isEmpty() : node + " " + node.usages();
-        FixedNode next = node.next();
-        node.setNext(null);
-        node.replaceAtPredecessor(next);
+        GraphUtil.unlinkFixedNode(node);
         node.safeDelete();
     }
 
@@ -288,9 +286,7 @@
 
     public void replaceFixedWithFloating(FixedWithNextNode node, FloatingNode replacement) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
-        FixedNode next = node.next();
-        node.setNext(null);
-        node.replaceAtPredecessor(next);
+        GraphUtil.unlinkFixedNode(node);
         node.replaceAtUsages(replacement);
         node.safeDelete();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,15 +24,13 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
- * The {@code PhiNode} represents the merging of dataflow in the graph. It refers to a merge and a
- * variable.
+ * Value {@link PhiNode}s merge data flow values at control flow merges.
  */
 @NodeInfo(nameTemplate = "ValuePhi({i#values})")
-public class ValuePhiNode extends PhiNode implements Simplifiable {
+public class ValuePhiNode extends PhiNode {
 
     @Input final NodeInputList<ValueNode> values;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -56,6 +56,26 @@
             return ConstantNode.forConstant(evalConst(forX.asConstant(), forY.asConstant()), null);
         }
         // Constant 0.0 can't be eliminated since it can affect the sign of the result.
+        // Constant -0.0 is an additive identity.
+        if (forY.isConstant()) {
+            Constant y = forY.asConstant();
+            switch (y.getKind()) {
+                case Float:
+                    // use Float.compare because -0.0f == 0.0f
+                    if (Float.compare(y.asFloat(), -0.0f) == 0) {
+                        return forX;
+                    }
+                    break;
+                case Double:
+                    // use Double.compare because -0.0 == 0.0
+                    if (Double.compare(y.asDouble(), -0.0) == 0) {
+                        return forX;
+                    }
+                    break;
+                default:
+                    throw GraalGraphInternalError.shouldNotReachHere();
+            }
+        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -52,6 +52,23 @@
         if (forX.isConstant() && forY.isConstant()) {
             return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
         }
+        if (forY.isConstant()) {
+            Constant y = forY.asConstant();
+            switch (y.getKind()) {
+                case Float:
+                    if (y.asFloat() == 1.0f) {
+                        return forX;
+                    }
+                    break;
+                case Double:
+                    if (y.asDouble() == 1.0) {
+                        return forX;
+                    }
+                    break;
+                default:
+                    throw GraalGraphInternalError.shouldNotReachHere();
+            }
+        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -55,6 +55,23 @@
         if (forX.isConstant()) {
             return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
         }
+        if (forY.isConstant()) {
+            Constant y = forY.asConstant();
+            switch (y.getKind()) {
+                case Float:
+                    if (y.asFloat() == 1.0f) {
+                        return forX;
+                    }
+                    break;
+                case Double:
+                    if (y.asDouble() == 1.0) {
+                        return forX;
+                    }
+                    break;
+                default:
+                    throw GraalGraphInternalError.shouldNotReachHere();
+            }
+        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -56,7 +56,27 @@
         if (forX.isConstant() && forY.isConstant()) {
             return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
         }
-        // Constant 0.0 can't be eliminated since it can affect the sign of the result.
+        // Constant -0.0 can't be eliminated since it can affect the sign of the result.
+        // Constant 0.0 is a subtractive identity.
+        if (forY.isConstant()) {
+            Constant y = forY.asConstant();
+            switch (y.getKind()) {
+                case Float:
+                    // use Float.compare because -0.0f == 0.0f
+                    if (Float.compare(y.asFloat(), 0.0f) == 0) {
+                        return forX;
+                    }
+                    break;
+                case Double:
+                    // use Double.compare because -0.0 == 0.0
+                    if (Double.compare(y.asDouble(), 0.0) == 0) {
+                        return forX;
+                    }
+                    break;
+                default:
+                    throw GraalGraphInternalError.shouldNotReachHere();
+            }
+        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Tue Jul 15 19:21:28 2014 -0700
@@ -37,7 +37,6 @@
     protected double probability;
     protected Loop<Block> loop;
 
-    protected List<Block> dominated;
     protected Block postdominator;
 
     protected Block(BeginNode node) {
@@ -98,13 +97,6 @@
         return b;
     }
 
-    public List<Block> getDominated() {
-        if (dominated == null) {
-            return Collections.emptyList();
-        }
-        return dominated;
-    }
-
     public Block getPostdominator() {
         return postdominator;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Tue Jul 15 19:15:46 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2012, 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.nodes.cfg;
-
-import java.util.*;
-
-import com.oracle.graal.compiler.common.cfg.*;
-
-public class CFGVerifier {
-
-    public static boolean verify(ControlFlowGraph cfg) {
-        for (Block block : cfg.getBlocks()) {
-            assert block.getId() >= 0;
-            assert cfg.getBlocks().get(block.getId()) == block;
-
-            for (Block pred : block.getPredecessors()) {
-                assert pred.getSuccessors().contains(block);
-                assert pred.getId() < block.getId() || pred.isLoopEnd();
-            }
-
-            for (Block sux : block.getSuccessors()) {
-                assert sux.getPredecessors().contains(block);
-                assert sux.getId() > block.getId() || sux.isLoopHeader();
-            }
-
-            if (block.getDominator() != null) {
-                assert block.getDominator().getId() < block.getId();
-                assert block.getDominator().getDominated().contains(block);
-            }
-            for (Block dominated : block.getDominated()) {
-                assert dominated.getId() > block.getId();
-                assert dominated.getDominator() == block;
-            }
-
-            Block postDominatorBlock = block.getPostdominator();
-            if (postDominatorBlock != null) {
-                assert block.getSuccessorCount() > 0 : "block has post-dominator block, but no successors";
-
-                BlockMap<Boolean> visitedBlocks = new BlockMap<>(cfg);
-                visitedBlocks.put(block, true);
-
-                Deque<Block> stack = new ArrayDeque<>();
-                for (Block sux : block.getSuccessors()) {
-                    visitedBlocks.put(sux, true);
-                    stack.push(sux);
-                }
-
-                while (stack.size() > 0) {
-                    Block tos = stack.pop();
-                    assert tos.getId() <= postDominatorBlock.getId();
-                    if (tos == postDominatorBlock) {
-                        continue; // found a valid path
-                    }
-                    assert tos.getSuccessorCount() > 0 : "no path found";
-
-                    for (Block sux : tos.getSuccessors()) {
-                        if (visitedBlocks.get(sux) == null) {
-                            visitedBlocks.put(sux, true);
-                            stack.push(sux);
-                        }
-                    }
-                }
-            }
-
-            assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().getHeader() == block : block.beginNode;
-        }
-
-        if (cfg.getLoops() != null) {
-            for (Loop<Block> loop : cfg.getLoops()) {
-                assert loop.getHeader().isLoopHeader();
-
-                for (Block block : loop.getBlocks()) {
-                    assert block.getId() >= loop.getHeader().getId();
-
-                    Loop<?> blockLoop = block.getLoop();
-                    while (blockLoop != loop) {
-                        assert blockLoop != null;
-                        blockLoop = blockLoop.getParent();
-                    }
-
-                    if (!(block.isLoopHeader() && block.getLoop() == loop)) {
-                        for (Block pred : block.getPredecessors()) {
-                            if (!loop.getBlocks().contains(pred)) {
-                                assert false : "Loop " + loop + " does not contain " + pred;
-                                return false;
-                            }
-                        }
-                    }
-                }
-
-                for (Block block : loop.getExits()) {
-                    assert block.getId() >= loop.getHeader().getId();
-
-                    Loop<?> blockLoop = block.getLoop();
-                    while (blockLoop != null) {
-                        blockLoop = blockLoop.getParent();
-                        assert blockLoop != loop;
-                    }
-                }
-            }
-        }
-
-        return true;
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Tue Jul 15 19:21:28 2014 -0700
@@ -49,7 +49,7 @@
             cfg.computeLoopInformation();
         }
         if (computeDominators) {
-            cfg.computeDominators();
+            AbstractControlFlowGraph.computeDominators(cfg);
         }
         if (computePostdominators) {
             cfg.computePostdominators();
@@ -309,49 +309,6 @@
         }
     }
 
-    private void computeDominators() {
-        assert reversePostOrder.get(0).getPredecessorCount() == 0 : "start block has no predecessor and therefore no dominator";
-        for (int i = 1; i < reversePostOrder.size(); i++) {
-            Block block = reversePostOrder.get(i);
-            assert block.getPredecessorCount() > 0;
-            Block dominator = null;
-            for (Block pred : block.getPredecessors()) {
-                if (!pred.isLoopEnd()) {
-                    dominator = commonDominator(dominator, pred);
-                }
-            }
-            setDominator(block, dominator);
-        }
-    }
-
-    private static void setDominator(Block block, Block dominator) {
-        block.setDominator(dominator);
-        if (dominator.dominated == null) {
-            dominator.dominated = new ArrayList<>();
-        }
-        dominator.dominated.add(block);
-    }
-
-    public static <T extends AbstractBlock<T>> T commonDominator(T a, T b) {
-        if (a == null) {
-            return b;
-        }
-        if (b == null) {
-            return a;
-        }
-        T iterA = a;
-        T iterB = b;
-        while (iterA != iterB) {
-            if (iterA.getId() > iterB.getId()) {
-                iterA = iterA.getDominator();
-            } else {
-                assert iterB.getId() > iterA.getId();
-                iterB = iterB.getDominator();
-            }
-        }
-        return iterA;
-    }
-
     private void computePostdominators() {
         outer: for (Block block : postOrder()) {
             if (block.isLoopEnd()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -92,12 +92,4 @@
         updateUsages(lastLocationAccess, newLla);
         lastLocationAccess = newLla;
     }
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -30,6 +30,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that is the sum of two other location nodes. Can represent locations in the form of
@@ -112,6 +113,11 @@
         return getY().generateAddress(builder, gen, xAddr);
     }
 
+    @Override
+    public IntegerStamp getDisplacementStamp() {
+        return StampTool.add(getX().getDisplacementStamp(), getY().getDisplacementStamp());
+    }
+
     @NodeIntrinsic
     public static native Location addLocation(Location x, Location y);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -73,4 +73,9 @@
     public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
         return gen.emitAddress(base, getDisplacement(), Value.ILLEGAL, 0);
     }
+
+    @Override
+    public IntegerStamp getDisplacementStamp() {
+        return StampFactory.forInteger(64, displacement, displacement);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -82,7 +82,8 @@
     @Override
     public boolean verify() {
         MemoryNode lla = getLastLocationAccess();
-        assert lla == null || lla.asMemoryCheckpoint() != null || lla.asMemoryPhi() != null : "lastLocationAccess of " + this + " should be a MemoryCheckpoint, but is " + lla;
+        assert lla == null || lla instanceof MemoryCheckpoint || lla instanceof MemoryProxy || lla instanceof MemoryPhiNode : "lastLocationAccess of " + this +
+                        " should be a MemoryCheckpoint, but is " + lla;
         return super.verify();
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
@@ -29,6 +30,7 @@
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that has a displacement and a scaled index. Can represent locations in the form of
@@ -101,6 +103,14 @@
     }
 
     @Override
+    public IntegerStamp getDisplacementStamp() {
+        assert indexScaling > 0 && CodeUtil.isPowerOf2(indexScaling);
+        int scale = CodeUtil.log2(indexScaling);
+        return (IntegerStamp) StampTool.add(StampFactory.forInteger(64, displacement, displacement),
+                        StampTool.signExtend(StampTool.leftShift(index.stamp(), StampFactory.forInteger(64, scale, scale)), 64));
+    }
+
+    @Override
     public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
         return gen.emitAddress(base, displacement, builder.operand(getIndex()), getIndexScaling());
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -64,4 +64,9 @@
     }
 
     public abstract Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base);
+
+    /**
+     * @return the range of the displacement as a 64-bit integer stamp
+     */
+    public abstract IntegerStamp getDisplacementStamp();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -62,14 +62,6 @@
         generator.getLIRGeneratorTool().emitMembar(barriers);
     }
 
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
-
     @SuppressWarnings("unused")
     @NodeIntrinsic
     public static void memoryBarrier(@ConstantNodeParameter int barriers) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -31,8 +31,4 @@
 public interface MemoryNode extends NodeInterface {
 
     ValueNode asNode();
-
-    MemoryCheckpoint asMemoryCheckpoint();
-
-    MemoryPhiNode asMemoryPhi();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -120,14 +120,6 @@
         return stateAfter;
     }
 
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
-
     // specialized on value type until boxing/unboxing is sorted out in intrinsification
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -70,12 +70,4 @@
         assertTrue(stateAfter() != null, "an exception handler needs a frame state");
         return super.verify();
     }
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -69,14 +69,6 @@
         gen.setResult(this, result);
     }
 
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
-
     public boolean canNullCheck() {
         return false;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -84,12 +84,4 @@
         Value result = gen.getLIRGeneratorTool().emitCompareAndSwap(address, gen.operand(getExpectedValue()), gen.operand(getNewValue()), Constant.INT_1, Constant.INT_0);
         gen.setResult(this, result);
     }
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -195,7 +195,7 @@
         if (targetMethod() == null) {
             return "??Invalid!";
         }
-        return MetaUtil.format("%h.%n", targetMethod());
+        return targetMethod().format("%h.%n");
     }
 
     public static MethodCallTargetNode find(StructuredGraph graph, ResolvedJavaMethod method) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -47,6 +47,10 @@
         this.escapedReturnValue = escapedReturnValue;
     }
 
+    public ValueNode getEscapedReturnValue() {
+        return escapedReturnValue;
+    }
+
     public void setEscapedReturnValue(ValueNode x) {
         updateUsages(escapedReturnValue, x);
         this.escapedReturnValue = x;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java	Tue Jul 15 19:21:28 2014 -0700
@@ -57,8 +57,7 @@
     boolean isStatic() default true;
 
     /**
-     * Gets the {@linkplain MetaUtil#signatureToMethodDescriptor signature} of the substituted
-     * method.
+     * Gets the {@linkplain Signature#toMethodDescriptor signature} of the substituted method.
      * <p>
      * If the default value is specified for this element, then the signature of the substituted
      * method is the same as the substitute method.
@@ -82,7 +81,7 @@
     /**
      * Determines if this method should be substituted in all cases, even if inlining thinks it is
      * not important.
-     * 
+     *
      * Note that this is still depending on whether inlining sees the correct call target, so it's
      * only a hard guarantee for static and special invocations.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Tue Jul 15 19:21:28 2014 -0700
@@ -298,6 +298,18 @@
         }
         int shiftBits = bits > 32 ? 6 : 5;
         long shiftMask = bits > 32 ? 0x3FL : 0x1FL;
+        if (shift.lowerBound() == shift.upperBound()) {
+            int shiftAmount = (int) (shift.lowerBound() & shiftMask);
+            if (shiftAmount == 0) {
+                return value;
+            }
+            // the mask of bits that will be lost or shifted into the sign bit
+            long removedBits = -1L << (bits - shiftAmount - 1);
+            if ((value.lowerBound() & removedBits) == 0 && (value.upperBound() & removedBits) == 0) {
+                // use a better stamp if neither lower nor upper bound can lose bits
+                return new IntegerStamp(bits, value.lowerBound() << shiftAmount, value.upperBound() << shiftAmount, value.downMask() << shiftAmount, value.upMask() << shiftAmount);
+            }
+        }
         if ((shift.lowerBound() >>> shiftBits) == (shift.upperBound() >>> shiftBits)) {
             long downMask = defaultMask;
             long upMask = 0;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Tue Jul 15 19:21:28 2014 -0700
@@ -157,10 +157,15 @@
                 killWithUnusedFloatingInputs(stateAfter);
             }
         }
+        unlinkFixedNode(fixed);
+        killWithUnusedFloatingInputs(fixed);
+    }
+
+    public static void unlinkFixedNode(FixedWithNextNode fixed) {
+        assert fixed.next() != null && fixed.predecessor() != null && fixed.isAlive();
         FixedNode next = fixed.next();
         fixed.setNext(null);
         fixed.replaceAtPredecessor(next);
-        killWithUnusedFloatingInputs(fixed);
     }
 
     public static void checkRedundantPhi(PhiNode phiNode) {
@@ -169,7 +174,7 @@
         }
 
         ValueNode singleValue = phiNode.singleValue();
-        if (singleValue != null) {
+        if (singleValue != PhiNode.NO_VALUE) {
             Collection<PhiNode> phiUsages = phiNode.usages().filter(PhiNode.class).snapshot();
             Collection<ProxyNode> proxyUsages = phiNode.usages().filter(ProxyNode.class).snapshot();
             phiNode.graph().replaceFloating(phiNode, singleValue);
@@ -338,6 +343,9 @@
                 v = ((ValueProxy) v).getOriginalNode();
             } else if (v instanceof PhiNode) {
                 v = ((PhiNode) v).singleValue();
+                if (v == PhiNode.NO_VALUE) {
+                    v = null;
+                }
             } else {
                 break;
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
@@ -102,7 +101,7 @@
         for (int objIndex = 0; objIndex < virtualObjects.size(); objIndex++) {
             VirtualObjectNode virtual = virtualObjects.get(objIndex);
             StringBuilder s = new StringBuilder();
-            s.append(MetaUtil.toJavaName(virtual.type(), false)).append("[");
+            s.append(virtual.type().toJavaName(false)).append("[");
             for (int i = 0; i < virtual.entryCount(); i++) {
                 ValueNode value = values.get(valuePos++);
                 s.append(i == 0 ? "" : ",").append(value == null ? "_" : value.toString(Verbosity.Id));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -63,7 +63,7 @@
     @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Name) {
-            return super.toString(Verbosity.Name) + " " + MetaUtil.toJavaName(type, false);
+            return super.toString(Verbosity.Name) + " " + type.toJavaName(false);
         } else {
             return super.toString(verbosity);
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Tue Jul 15 19:21:28 2014 -0700
@@ -54,6 +54,7 @@
 
     @Override
     protected void run(final StructuredGraph graph) {
+        assert graph.hasValueProxies() : "ConvertDeoptimizeToGuardPhase always creates proxies";
         if (graph.getNodes(DeoptimizeNode.class).isEmpty()) {
             return;
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Tue Jul 15 19:21:28 2014 -0700
@@ -43,10 +43,9 @@
 
 public class FloatingReadPhase extends Phase {
 
-    public enum ExecutionMode {
-        ANALYSIS_ONLY,
-        CREATE_FLOATING_READS
-    }
+    private boolean createFloatingReads;
+    private boolean createMemoryMapNodes;
+    private boolean updateExistingPhis;
 
     public static class MemoryMapImpl implements MemoryMap {
 
@@ -90,14 +89,23 @@
         }
     }
 
-    private final ExecutionMode execmode;
-
     public FloatingReadPhase() {
-        this(ExecutionMode.CREATE_FLOATING_READS);
+        this(true, false, false);
     }
 
-    public FloatingReadPhase(ExecutionMode execmode) {
-        this.execmode = execmode;
+    /**
+     * @param createFloatingReads specifies whether {@link FloatableAccessNode}s like
+     *            {@link ReadNode} should be converted into floating nodes (e.g.,
+     *            {@link FloatingReadNode}s) where possible
+     * @param createMemoryMapNodes a {@link MemoryMapNode} will be created for each return if this
+     *            is true
+     * @param updateExistingPhis if true, then existing {@link MemoryPhiNode}s in the graph will be
+     *            updated
+     */
+    public FloatingReadPhase(boolean createFloatingReads, boolean createMemoryMapNodes, boolean updateExistingPhis) {
+        this.createFloatingReads = createFloatingReads;
+        this.createMemoryMapNodes = createMemoryMapNodes;
+        this.updateExistingPhis = updateExistingPhis;
     }
 
     /**
@@ -127,7 +135,7 @@
         ReentrantNodeIterator.apply(new CollectMemoryCheckpointsClosure(modifiedInLoops), graph.start(), new HashSet<LocationIdentity>());
         HashSetNodeEventListener listener = new HashSetNodeEventListener(EnumSet.of(NODE_ADDED, ZERO_USAGES));
         try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
-            ReentrantNodeIterator.apply(new FloatingReadClosure(modifiedInLoops, execmode), graph.start(), new MemoryMapImpl(graph.start()));
+            ReentrantNodeIterator.apply(new FloatingReadClosure(modifiedInLoops, createFloatingReads, createMemoryMapNodes, updateExistingPhis), graph.start(), new MemoryMapImpl(graph.start()));
         }
 
         for (Node n : removeExternallyUsedNodes(listener.getNodes())) {
@@ -136,13 +144,13 @@
                 GraphUtil.killWithUnusedFloatingInputs(n);
             }
         }
-        if (execmode == ExecutionMode.CREATE_FLOATING_READS) {
+        if (createFloatingReads) {
             assert !graph.isAfterFloatingReadPhase();
             graph.setAfterFloatingReadPhase(true);
         }
     }
 
-    public static MemoryMapImpl mergeMemoryMaps(MergeNode merge, List<? extends MemoryMap> states) {
+    public static MemoryMapImpl mergeMemoryMaps(MergeNode merge, List<? extends MemoryMap> states, boolean updateExistingPhis) {
         MemoryMapImpl newState = new MemoryMapImpl();
 
         Set<LocationIdentity> keys = new HashSet<>();
@@ -151,6 +159,17 @@
         }
         assert !keys.contains(FINAL_LOCATION);
 
+        Map<LocationIdentity, MemoryPhiNode> existingPhis = null;
+        if (updateExistingPhis) {
+            for (MemoryPhiNode phi : merge.phis().filter(MemoryPhiNode.class)) {
+                if (existingPhis == null) {
+                    existingPhis = newIdentityMap();
+                }
+                phi.values().clear();
+                existingPhis.put(phi.getLocationIdentity(), phi);
+            }
+        }
+
         for (LocationIdentity key : keys) {
             int mergedStatesCount = 0;
             boolean isPhi = false;
@@ -158,14 +177,17 @@
             for (MemoryMap state : states) {
                 MemoryNode last = state.getLastLocationAccess(key);
                 if (isPhi) {
-                    merged.asMemoryPhi().addInput(ValueNodeUtil.asNode(last));
+                    ((MemoryPhiNode) merged).addInput(ValueNodeUtil.asNode(last));
                 } else {
                     if (merged == last) {
                         // nothing to do
                     } else if (merged == null) {
                         merged = last;
                     } else {
-                        MemoryPhiNode phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key));
+                        MemoryPhiNode phi = null;
+                        if (existingPhis == null || (phi = existingPhis.remove(key)) == null) {
+                            phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key));
+                        }
                         for (int j = 0; j < mergedStatesCount; j++) {
                             phi.addInput(ValueNodeUtil.asNode(merged));
                         }
@@ -178,6 +200,11 @@
             }
             newState.lastMemorySnapshot.put(key, merged);
         }
+        if (existingPhis != null) {
+            for (Map.Entry<LocationIdentity, MemoryPhiNode> entry : existingPhis.entrySet()) {
+                entry.getValue().replaceAndDelete(newState.getLastLocationAccess(entry.getKey()).asNode());
+            }
+        }
         return newState;
 
     }
@@ -237,11 +264,15 @@
     private static class FloatingReadClosure extends NodeIteratorClosure<MemoryMapImpl> {
 
         private final Map<LoopBeginNode, Set<LocationIdentity>> modifiedInLoops;
-        private final ExecutionMode execmode;
+        private boolean createFloatingReads;
+        private boolean createMemoryMapNodes;
+        private boolean updateExistingPhis;
 
-        public FloatingReadClosure(Map<LoopBeginNode, Set<LocationIdentity>> modifiedInLoops, ExecutionMode execmode) {
+        public FloatingReadClosure(Map<LoopBeginNode, Set<LocationIdentity>> modifiedInLoops, boolean createFloatingReads, boolean createMemoryMapNodes, boolean updateExistingPhis) {
             this.modifiedInLoops = modifiedInLoops;
-            this.execmode = execmode;
+            this.createFloatingReads = createFloatingReads;
+            this.createMemoryMapNodes = createMemoryMapNodes;
+            this.updateExistingPhis = updateExistingPhis;
         }
 
         @Override
@@ -250,7 +281,7 @@
                 processAccess((MemoryAccess) node, state);
             }
 
-            if (node instanceof FloatableAccessNode && execmode == ExecutionMode.CREATE_FLOATING_READS) {
+            if (createFloatingReads & node instanceof FloatableAccessNode) {
                 processFloatable((FloatableAccessNode) node, state);
             } else if (node instanceof MemoryCheckpoint.Single) {
                 processCheckpoint((MemoryCheckpoint.Single) node, state);
@@ -259,7 +290,7 @@
             }
             assert MemoryCheckpoint.TypeAssertion.correctType(node) : node;
 
-            if (execmode == ExecutionMode.ANALYSIS_ONLY && node instanceof ReturnNode) {
+            if (createMemoryMapNodes && node instanceof ReturnNode) {
                 ((ReturnNode) node).setMemoryMap(node.graph().unique(new MemoryMapNode(state.lastMemorySnapshot)));
             }
             return state;
@@ -309,7 +340,7 @@
 
         @Override
         protected MemoryMapImpl merge(MergeNode merge, List<MemoryMapImpl> states) {
-            return mergeMemoryMaps(merge, states);
+            return mergeMemoryMaps(merge, states, updateExistingPhis);
         }
 
         @Override
@@ -339,10 +370,25 @@
             }
 
             Map<LocationIdentity, MemoryPhiNode> phis = new HashMap<>();
+
+            if (updateExistingPhis) {
+                for (MemoryPhiNode phi : loop.phis().filter(MemoryPhiNode.class)) {
+                    if (modifiedLocations.contains(phi.getLocationIdentity())) {
+                        phi.values().clear();
+                        phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(phi.getLocationIdentity())));
+                        phis.put(phi.getLocationIdentity(), phi);
+                    } else {
+                        phi.replaceAndDelete(initialState.getLastLocationAccess(phi.getLocationIdentity()).asNode());
+                    }
+                }
+            }
+
             for (LocationIdentity location : modifiedLocations) {
-                MemoryPhiNode phi = loop.graph().addWithoutUnique(new MemoryPhiNode(loop, location));
-                phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(location)));
-                phis.put(location, phi);
+                if (!updateExistingPhis || !phis.containsKey(location)) {
+                    MemoryPhiNode phi = loop.graph().addWithoutUnique(new MemoryPhiNode(loop, location));
+                    phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(location)));
+                    phis.put(location, phi);
+                }
             }
             for (Map.Entry<LocationIdentity, MemoryPhiNode> entry : phis.entrySet()) {
                 initialState.lastMemorySnapshot.put(entry.getKey(), entry.getValue());
@@ -358,16 +404,6 @@
                     phi.initializeValueAt(endIndex, ValueNodeUtil.asNode(entry.getValue().getLastLocationAccess(key)));
                 }
             }
-            for (Map.Entry<LoopExitNode, MemoryMapImpl> entry : loopInfo.exitStates.entrySet()) {
-                LoopExitNode exit = entry.getKey();
-                MemoryMapImpl state = entry.getValue();
-                for (LocationIdentity location : modifiedLocations) {
-                    MemoryNode lastAccessAtExit = state.lastMemorySnapshot.get(location);
-                    if (lastAccessAtExit != null) {
-                        state.lastMemorySnapshot.put(location, MemoryProxyNode.forMemory(lastAccessAtExit, exit, location, loop.graph()));
-                    }
-                }
-            }
             return loopInfo.exitStates;
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReductionPhase.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReductionPhase.java	Tue Jul 15 19:21:28 2014 -0700
@@ -44,7 +44,7 @@
     protected final void run(StructuredGraph graph, PhaseContext context) {
         try (Debug.Scope s = Debug.scope("FlowSensitiveReduction")) {
             if (graph.isOSR()) {
-                Debug.log("Skipping OSR method %s", graph.method() == null ? "" : MetaUtil.format("%H.%n", graph.method()));
+                Debug.log("Skipping OSR method %s", graph.method() == null ? "" : graph.method().format("%H.%n"));
                 return;
             }
             Debug.dump(graph, "FlowSensitiveReduction initial");
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Tue Jul 15 19:21:28 2014 -0700
@@ -146,9 +146,9 @@
 
     private static String methodName(ResolvedJavaMethod method, Invoke invoke) {
         if (invoke != null && invoke.stateAfter() != null) {
-            return methodName(invoke.stateAfter(), invoke.bci()) + ": " + MetaUtil.format("%H.%n(%p):%r", method) + " (" + method.getCodeSize() + " bytes)";
+            return methodName(invoke.stateAfter(), invoke.bci()) + ": " + method.format("%H.%n(%p):%r") + " (" + method.getCodeSize() + " bytes)";
         } else {
-            return MetaUtil.format("%H.%n(%p):%r", method) + " (" + method.getCodeSize() + " bytes)";
+            return method.format("%H.%n(%p):%r") + " (" + method.getCodeSize() + " bytes)";
         }
     }
 
@@ -168,7 +168,7 @@
             sb.append(methodName(frameState.outerFrameState(), frameState.outerFrameState().bci));
             sb.append("->");
         }
-        sb.append(MetaUtil.format("%h.%n", frameState.method()));
+        sb.append(frameState.method().format("%h.%n"));
         sb.append("@").append(bci);
         return sb.toString();
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java	Tue Jul 15 19:21:28 2014 -0700
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.api.code.Assumptions;
 import com.oracle.graal.api.meta.MetaAccessProvider;
-import com.oracle.graal.api.meta.MetaUtil;
 import com.oracle.graal.api.meta.ResolvedJavaMethod;
 import com.oracle.graal.nodes.Invoke;
 import com.oracle.graal.phases.common.inlining.InliningUtil;
@@ -62,6 +61,6 @@
 
     @Override
     public String toString() {
-        return "assumption " + MetaUtil.format("%H.%n(%p):%r", concrete);
+        return "assumption " + concrete.format("%H.%n(%p):%r");
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java	Tue Jul 15 19:21:28 2014 -0700
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.api.code.Assumptions;
 import com.oracle.graal.api.meta.MetaAccessProvider;
-import com.oracle.graal.api.meta.MetaUtil;
 import com.oracle.graal.api.meta.ResolvedJavaMethod;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.Invoke;
@@ -88,7 +87,7 @@
 
     @Override
     public String toString() {
-        return "exact " + MetaUtil.format("%H.%n(%p):%r", concrete);
+        return "exact " + concrete.format("%H.%n(%p):%r");
     }
 
     @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Tue Jul 15 19:21:28 2014 -0700
@@ -545,7 +545,7 @@
         builder.append(concretes.size());
         builder.append(" methods [ ");
         for (int i = 0; i < concretes.size(); i++) {
-            builder.append(MetaUtil.format("  %H.%n(%p):%r", concretes.get(i)));
+            builder.append(concretes.get(i).format("  %H.%n(%p):%r"));
         }
         builder.append(" ], ");
         builder.append(ptypes.size());
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java	Tue Jul 15 19:21:28 2014 -0700
@@ -118,7 +118,7 @@
 
     @Override
     public String toString() {
-        return "type-checked with type " + type.getName() + " and method " + MetaUtil.format("%H.%n(%p):%r", concrete);
+        return "type-checked with type " + type.getName() + " and method " + concrete.format("%H.%n(%p):%r");
     }
 
     public boolean shouldInline() {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.phases.common.inlining.walker;
 
-import com.oracle.graal.api.meta.MetaUtil;
 import com.oracle.graal.api.meta.ResolvedJavaMethod;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.graph.FixedNodeProbabilityCache;
@@ -209,6 +208,6 @@
 
     @Override
     public String toString() {
-        return (graph != null ? MetaUtil.format("%H.%n(%p)", method()) : "<null method>") + remainingInvokes;
+        return (graph != null ? method().format("%H.%n(%p)") : "<null method>") + remainingInvokes;
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java	Tue Jul 15 19:21:28 2014 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.phases.common.inlining.walker;
 
 import com.oracle.graal.api.code.Assumptions;
-import com.oracle.graal.api.meta.MetaUtil;
 import com.oracle.graal.api.meta.ResolvedJavaMethod;
 import com.oracle.graal.nodes.CallTargetNode;
 import com.oracle.graal.nodes.java.MethodCallTargetNode;
@@ -152,7 +151,7 @@
         CallTargetNode callTarget = callee.invoke().callTarget();
         if (callTarget instanceof MethodCallTargetNode) {
             ResolvedJavaMethod calleeMethod = ((MethodCallTargetNode) callTarget).targetMethod();
-            return MetaUtil.format("Invoke#%H.%n(%p)", calleeMethod);
+            return calleeMethod.format("Invoke#%H.%n(%p)");
         } else {
             return "Invoke#" + callTarget.targetName();
         }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Tue Jul 15 19:21:28 2014 -0700
@@ -38,6 +38,8 @@
  */
 public abstract class BasePhase<C> {
 
+    public static final int PHASE_DUMP_LEVEL = 1;
+
     private CharSequence name;
 
     /**
@@ -97,8 +99,8 @@
             this.run(graph, context);
             executionCount.increment();
             inputNodesCount.add(graph.getNodeCount());
-            if (dumpGraph && Debug.isDumpEnabled()) {
-                Debug.dump(graph, "After phase %s", getName());
+            if (dumpGraph && Debug.isDumpEnabled(PHASE_DUMP_LEVEL)) {
+                Debug.dump(PHASE_DUMP_LEVEL, graph, "After phase %s", getName());
             }
             if (Debug.isVerifyEnabled()) {
                 Debug.verify(graph, "After phase %s", getName());
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,8 +24,7 @@
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
-import static com.oracle.graal.nodes.cfg.ControlFlowGraph.*;
-import static com.oracle.graal.compiler.common.cfg.AbstractBlock.*;
+import static com.oracle.graal.compiler.common.cfg.AbstractControlFlowGraph.*;
 
 import java.util.*;
 
@@ -654,7 +653,7 @@
 
         @Override
         public void apply(Block newBlock) {
-            this.block = commonDominator(this.block, newBlock);
+            this.block = commonDominatorTyped(this.block, newBlock);
         }
     }
 
@@ -1050,7 +1049,7 @@
             LocationIdentity readLocation = frn.location().getLocationIdentity();
             assert readLocation != FINAL_LOCATION;
             if (frn.getLastLocationAccess() == node) {
-                assert identity == ANY_LOCATION || readLocation == identity : "location doesn't match: " + readLocation + ", " + identity;
+                assert identity == ANY_LOCATION || readLocation == identity || node instanceof MemoryCheckpoint.Multi : "location doesn't match: " + readLocation + ", " + identity;
                 state.clearBeforeLastLocation(frn);
             } else if (!state.isBeforeLastLocation(frn) && (readLocation == identity || (node != getCFG().graph.start() && ANY_LOCATION == identity))) {
                 state.removeRead(frn);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Tue Jul 15 19:21:28 2014 -0700
@@ -107,6 +107,12 @@
         }
     }
 
+    public Suites(PhaseSuite<HighTierContext> highTier, PhaseSuite<MidTierContext> midTier, PhaseSuite<LowTierContext> lowTier) {
+        this.highTier = highTier;
+        this.midTier = midTier;
+        this.lowTier = lowTier;
+    }
+
     private Suites(CompilerConfiguration config) {
         highTier = config.createHighTier();
         midTier = config.createMidTier();
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyDebugUsage.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyDebugUsage.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.phases.verify;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
@@ -58,7 +56,7 @@
                                     if (holder.equals("Ljava/lang/StringBuilder;") || holder.equals("Ljava/lang/StringBuffer;")) {
                                         StackTraceElement e = graph.method().asStackTraceElement(invoke.bci());
                                         throw new VerificationError(String.format("%s: parameter %d of call to %s appears to be a String concatenation expression.%n"
-                                                        + "    Use one of the multi-parameter Debug.log() methods or Debug.logv() instead.", e, argIdx, format("%H.%n(%p)", callee)));
+                                                        + "    Use one of the multi-parameter Debug.log() methods or Debug.logv() instead.", e, argIdx, callee.format("%H.%n(%p)")));
                                     }
                                 }
                             }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Tue Jul 15 19:21:28 2014 -0700
@@ -287,7 +287,7 @@
         } else if (object instanceof JavaType) {
             JavaType type = (JavaType) object;
             writeByte(POOL_CLASS);
-            writeString(MetaUtil.toJavaName(type));
+            writeString(type.toJavaName());
             writeByte(KLASS);
         } else if (object instanceof NodeClass) {
             NodeClass nodeClass = (NodeClass) object;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Jul 15 19:21:28 2014 -0700
@@ -186,7 +186,7 @@
         if (!inFixedSchedule(input)) {
             Block inputBlock = block;
             if (latestScheduling.get(input) != null) {
-                inputBlock = ControlFlowGraph.commonDominator(inputBlock, latestScheduling.get(input));
+                inputBlock = AbstractControlFlowGraph.commonDominatorTyped(inputBlock, latestScheduling.get(input));
             }
             if (inputBlock != latestScheduling.get(input)) {
                 latestScheduling.set(input, inputBlock);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Tue Jul 15 19:21:28 2014 -0700
@@ -106,8 +106,8 @@
      */
     public void printCompilation(JavaMethod method) {
         begin("compilation");
-        out.print("name \" ").print(MetaUtil.format("%H::%n", method)).println('"');
-        out.print("method \"").print(MetaUtil.format("%f %r %H.%n(%p)", method)).println('"');
+        out.print("name \" ").print(method.format("%H::%n")).println('"');
+        out.print("method \"").print(method.format("%f %r %H.%n(%p)")).println('"');
         out.print("date ").println(System.currentTimeMillis());
         end("compilation");
     }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Tue Jul 15 19:21:28 2014 -0700
@@ -210,7 +210,7 @@
             JavaMethod method = asJavaMethod(o);
             if (method != null) {
                 if (lastMethodOrGraph == null || asJavaMethod(lastMethodOrGraph) == null || !asJavaMethod(lastMethodOrGraph).equals(method)) {
-                    result.add(MetaUtil.format("%H::%n(%p)", method));
+                    result.add(method.format("%H::%n(%p)"));
                 } else {
                     // This prevents multiple adjacent method context objects for the same method
                     // from resulting in multiple IGV tree levels. This works on the
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Tue Jul 15 19:21:28 2014 -0700
@@ -183,7 +183,7 @@
             ResolvedJavaType arrayType = StampTool.typeOrNull(array);
             if (arrayType != null && StampTool.isExactType(array)) {
                 ResolvedJavaType elementType = arrayType.getComponentType();
-                if (!MetaUtil.isJavaLangObject(elementType)) {
+                if (!elementType.isJavaLangObject()) {
                     checkCastNode = graph.add(new CheckCastNode(elementType, value, null, true));
                     graph.addBeforeFixed(storeIndexed, checkCastNode);
                     value = checkCastNode;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Jul 15 19:21:28 2014 -0700
@@ -83,7 +83,7 @@
             assert target.getAnnotation(Fold.class) == null;
             assert target.isStatic() : "node intrinsic must be static: " + target;
 
-            ResolvedJavaType[] parameterTypes = resolveJavaTypes(signatureToTypes(target), declaringClass);
+            ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass);
 
             // Prepare the arguments for the reflective constructor call on the node class.
             Constant[] nodeConstructorArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false);
@@ -102,7 +102,7 @@
             // Clean up checkcast instructions inserted by javac if the return type is generic.
             cleanUpReturnList.add(newInstance);
         } else if (isFoldable(target)) {
-            ResolvedJavaType[] parameterTypes = resolveJavaTypes(signatureToTypes(target), declaringClass);
+            ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass);
 
             // Prepare the arguments for the reflective method call
             Constant[] arguments = prepareArguments(methodCallTargetNode, parameterTypes, target, true);
@@ -165,7 +165,7 @@
                 parameterIndex--;
             }
             ValueNode argument = arguments.get(i);
-            if (folding || getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) {
+            if (folding || target.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex) != null) {
                 if (!(argument instanceof ConstantNode)) {
                     return null;
                 }
@@ -203,8 +203,8 @@
         } else {
             result = providers.getMetaAccess().lookupJavaType(intrinsic.value());
         }
-        assert providers.getMetaAccess().lookupJavaType(ValueNode.class).isAssignableFrom(result) : "Node intrinsic class " + toJavaName(result, false) + " derived from @" +
-                        NodeIntrinsic.class.getSimpleName() + " annotation on " + format("%H.%n(%p)", target) + " is not a subclass of " + ValueNode.class;
+        assert providers.getMetaAccess().lookupJavaType(ValueNode.class).isAssignableFrom(result) : "Node intrinsic class " + result.toJavaName(false) + " derived from @" +
+                        NodeIntrinsic.class.getSimpleName() + " annotation on " + target.format("%H.%n(%p)") + " is not a subclass of " + ValueNode.class;
         return result;
     }
 
@@ -221,12 +221,12 @@
                     constructor = c;
                     arguments = match;
                 } else {
-                    throw new GraalInternalError("Found multiple constructors in %s compatible with signature %s: %s, %s", toJavaName(nodeClass), sigString(parameterTypes), constructor, c);
+                    throw new GraalInternalError("Found multiple constructors in %s compatible with signature %s: %s, %s", nodeClass.toJavaName(), sigString(parameterTypes), constructor, c);
                 }
             }
         }
         if (constructor == null) {
-            throw new GraalInternalError("Could not find constructor in %s compatible with signature %s", toJavaName(nodeClass), sigString(parameterTypes));
+            throw new GraalInternalError("Could not find constructor in %s compatible with signature %s", nodeClass.toJavaName(), sigString(parameterTypes));
         }
 
         try {
@@ -247,14 +247,14 @@
             if (i != 0) {
                 sb.append(", ");
             }
-            sb.append(toJavaName(types[i]));
+            sb.append(types[i].toJavaName());
         }
         return sb.append(")").toString();
     }
 
     private static boolean containsInjected(ResolvedJavaMethod c, int start, int end) {
         for (int i = start; i < end; i++) {
-            if (getParameterAnnotation(InjectedNodeParameter.class, i, c) != null) {
+            if (c.getParameterAnnotation(InjectedNodeParameter.class, i) != null) {
                 return true;
             }
         }
@@ -265,10 +265,10 @@
         Constant[] arguments = null;
         Constant[] injected = null;
 
-        ResolvedJavaType[] signature = resolveJavaTypes(signatureToTypes(c.getSignature(), null), c.getDeclaringClass());
+        ResolvedJavaType[] signature = resolveJavaTypes(c.getSignature().toParameterTypes(null), c.getDeclaringClass());
         MetaAccessProvider metaAccess = providers.getMetaAccess();
         for (int i = 0; i < signature.length; i++) {
-            if (getParameterAnnotation(InjectedNodeParameter.class, i, c) != null) {
+            if (c.getParameterAnnotation(InjectedNodeParameter.class, i) != null) {
                 injected = injected == null ? new Constant[1] : Arrays.copyOf(injected, injected.length + 1);
                 if (signature[i].equals(metaAccess.lookupJavaType(MetaAccessProvider.class))) {
                     injected[injected.length - 1] = snippetReflection.forObject(metaAccess);
@@ -279,7 +279,7 @@
                 } else if (signature[i].equals(metaAccess.lookupJavaType(SnippetReflectionProvider.class))) {
                     injected[injected.length - 1] = snippetReflection.forObject(snippetReflection);
                 } else {
-                    throw new GraalInternalError("Cannot handle injected argument of type %s in %s", toJavaName(signature[i]), format("%H.%n(%p)", c));
+                    throw new GraalInternalError("Cannot handle injected argument of type %s in %s", signature[i].toJavaName(), c.format("%H.%n(%p)"));
                 }
             } else {
                 if (i > 0) {
@@ -347,9 +347,7 @@
                 for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
                     checkCheckCastUsage(graph, newInstance, checkCastNode, checkCastUsage);
                 }
-                FixedNode next = checkCastNode.next();
-                checkCastNode.setNext(null);
-                checkCastNode.replaceAtPredecessor(next);
+                GraphUtil.unlinkFixedNode(checkCastNode);
                 GraphUtil.killCFG(checkCastNode);
             }
         }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java	Tue Jul 15 19:21:28 2014 -0700
@@ -58,7 +58,7 @@
     }
 
     private static void error(MethodCallTargetNode n, String failedAction) throws GraalInternalError {
-        String context = MetaUtil.format("%H.%n", n.graph().method());
+        String context = n.graph().method().format("%H.%n");
         String target = n.invoke().callTarget().targetName();
         throw new GraalInternalError(failedAction + " of call to '" + target + "' in '" + context + "' failed, most likely due to a parameter annotated with @" +
                         ConstantNodeParameter.class.getSimpleName() + " not being resolvable to a constant during compilation");
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Jul 15 19:21:28 2014 -0700
@@ -350,7 +350,7 @@
             original = metaAccess.lookupJavaConstructor((Constructor<?>) originalMember);
         }
         if (Debug.isLogEnabled()) {
-            Debug.log("substitution: %s --> %s", MetaUtil.format("%H.%n(%p) %r", original), MetaUtil.format("%H.%n(%p) %r", substitute));
+            Debug.log("substitution: %s --> %s", original.format("%H.%n(%p) %r"), substitute.format("%H.%n(%p) %r"));
         }
 
         cr.methodSubstitutions.put(original, substitute);
@@ -645,8 +645,8 @@
                                     targetGraph = intrinsicGraph;
                                 } else {
                                     if (callee.getName().startsWith("$jacoco")) {
-                                        throw new GraalInternalError("Parsing call to JaCoCo instrumentation method " + format("%H.%n(%p)", callee) + " from " + format("%H.%n(%p)", methodToParse) +
-                                                        " while preparing replacement " + format("%H.%n(%p)", method) + ". Placing \"//JaCoCo Exclude\" anywhere in " +
+                                        throw new GraalInternalError("Parsing call to JaCoCo instrumentation method " + callee.format("%H.%n(%p)") + " from " + methodToParse.format("%H.%n(%p)") +
+                                                        " while preparing replacement " + method.format("%H.%n(%p)") + ". Placing \"//JaCoCo Exclude\" anywhere in " +
                                                         methodToParse.getDeclaringClass().getSourceFileName() + " should fix this.");
                                     }
                                     targetGraph = parseGraph(callee, policy, inliningDepth + 1);
@@ -715,7 +715,7 @@
             dimensions++;
         }
 
-        Class<?> baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveClass(toJavaName(base), false);
+        Class<?> baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveClass(base.toJavaName(), false);
         return dimensions == 0 ? baseClass : Array.newInstance(baseClass, new int[dimensions]).getClass();
     }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Jul 15 19:21:28 2014 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.replacements;
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.debug.Debug.*;
 import static com.oracle.graal.graph.util.CollectionsAccess.*;
@@ -91,8 +90,8 @@
                 constantParameters = new boolean[count];
                 varargsParameters = new boolean[count];
                 for (int i = 0; i < count; i++) {
-                    constantParameters[i] = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method) != null;
-                    varargsParameters[i] = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method) != null;
+                    constantParameters[i] = method.getParameterAnnotation(ConstantParameter.class, i) != null;
+                    varargsParameters[i] = method.getParameterAnnotation(VarargsParameter.class, i) != null;
 
                     assert !constantParameters[i] || !varargsParameters[i] : "Parameter cannot be annotated with both @" + ConstantParameter.class.getSimpleName() + " and @" +
                                     VarargsParameter.class.getSimpleName();
@@ -152,7 +151,7 @@
             this.method = method;
             instantiationCounter = Debug.metric("SnippetInstantiationCount[%s]", method);
             instantiationTimer = Debug.timer("SnippetInstantiationTime[%s]", method);
-            assert method.isStatic() : "snippet method must be static: " + MetaUtil.format("%H.%n", method);
+            assert method.isStatic() : "snippet method must be static: " + method.format("%H.%n");
         }
 
         private int templateCount;
@@ -161,7 +160,7 @@
             templateCount++;
             if (UseSnippetTemplateCache && templateCount > MaxTemplatesPerSnippet) {
                 PrintStream err = System.err;
-                err.printf("WARNING: Exceeded %d templates for snippet %s%n" + "         Adjust maximum with %s system property%n", MaxTemplatesPerSnippet, format("%h.%n(%p)", method),
+                err.printf("WARNING: Exceeded %d templates for snippet %s%n" + "         Adjust maximum with %s system property%n", MaxTemplatesPerSnippet, method.format("%h.%n(%p)"),
                                 MAX_TEMPLATES_PER_SNIPPET_PROPERTY_NAME);
             }
         }
@@ -260,7 +259,7 @@
         @Override
         public String toString() {
             StringBuilder result = new StringBuilder();
-            result.append("Parameters<").append(MetaUtil.format("%h.%n", info.method)).append(" [");
+            result.append("Parameters<").append(info.method.format("%h.%n")).append(" [");
             String sep = "";
             for (int i = 0; i < info.getParameterCount(); i++) {
                 result.append(sep);
@@ -497,7 +496,7 @@
      * Determines if any parameter of a given method is annotated with {@link ConstantParameter}.
      */
     public static boolean hasConstantParameter(ResolvedJavaMethod method) {
-        for (ConstantParameter p : MetaUtil.getParameterAnnotations(ConstantParameter.class, method)) {
+        for (ConstantParameter p : method.getParameterAnnotations(ConstantParameter.class)) {
             if (p != null) {
                 return true;
             }
@@ -669,7 +668,7 @@
 
         assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders);
 
-        new FloatingReadPhase(FloatingReadPhase.ExecutionMode.ANALYSIS_ONLY).apply(snippetCopy);
+        new FloatingReadPhase(false, true, false).apply(snippetCopy);
 
         MemoryAnchorNode memoryAnchor = snippetCopy.add(new MemoryAnchorNode());
         snippetCopy.start().replaceAtUsages(InputType.Memory, memoryAnchor);
@@ -694,7 +693,7 @@
             List<MemoryMapNode> memMaps = returnNodes.stream().map(n -> n.getMemoryMap()).collect(Collectors.toList());
             ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes, null);
             this.returnNode = snippet.add(new ReturnNode(returnValue));
-            MemoryMapImpl mmap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps);
+            MemoryMapImpl mmap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps, false);
             MemoryMapNode memoryMap = snippet.unique(new MemoryMapNode(mmap.getMap()));
             this.returnNode.setMemoryMap(memoryMap);
             for (MemoryMapNode mm : memMaps) {
@@ -747,7 +746,7 @@
     private static boolean checkVarargs(MetaAccessProvider metaAccess, final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) {
         ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass());
         assert type.isArray() : "varargs parameter must be an array type";
-        assert type.getComponentType().isAssignableFrom(metaAccess.lookupJavaType(varargs.componentType)) : "componentType for " + name + " not matching " + MetaUtil.toJavaName(type) + " instance: " +
+        assert type.getComponentType().isAssignableFrom(metaAccess.lookupJavaType(varargs.componentType)) : "componentType for " + name + " not matching " + type.toJavaName() + " instance: " +
                         varargs.componentType;
         return true;
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
@@ -127,6 +128,9 @@
      */
     protected StructuredGraph lowerReplacement(final StructuredGraph replacementGraph, LoweringTool tool) {
         final PhaseContext c = new PhaseContext(tool.getMetaAccess(), tool.getConstantReflection(), tool.getLowerer(), tool.getReplacements(), tool.assumptions());
+        if (!graph().hasValueProxies()) {
+            new RemoveValueProxyPhase().apply(replacementGraph);
+        }
         GuardsStage guardsStage = graph().getGuardsStage();
         if (guardsStage.ordinal() >= GuardsStage.FIXED_DEOPTS.ordinal()) {
             new GuardLoweringPhase().apply(replacementGraph, null);
@@ -164,7 +168,9 @@
             InliningUtil.inline(invoke, replacementGraph, false, null);
             Debug.dump(graph(), "After inlining replacement %s", replacementGraph);
         } else {
-            assert stateAfter() != null : "cannot lower to invoke without state: " + this;
+            if (stateAfter() == null) {
+                throw new GraalInternalError("cannot lower to invoke without state: %s", this);
+            }
             invoke.lower(tool);
         }
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -62,14 +62,6 @@
         return LocationIdentity.ANY_LOCATION;
     }
 
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
-
     protected void replaceSnippetInvokes(StructuredGraph snippetGraph) {
         for (MethodCallTargetNode call : snippetGraph.getNodes(MethodCallTargetNode.class)) {
             Invoke invoke = call.invoke();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -44,12 +44,4 @@
     public Node canonical(CanonicalizerTool tool) {
         return usages().isEmpty() ? null : this;
     }
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return null;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Tue Jul 15 19:21:28 2014 -0700
@@ -113,22 +113,16 @@
 
     @Override
     public Object call(Object... args) {
+        if (profiledArgumentTypesAssumption != null && profiledArgumentTypesAssumption.isValid()) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            profiledArgumentTypesAssumption.invalidate();
+            profiledArgumentTypes = null;
+        }
         return callBoundary(args);
     }
 
     public Object callDirect(Object... args) {
-        if (profiledArgumentTypesAssumption == null) {
-            CompilerDirectives.transferToInterpreter();
-            profiledArgumentTypesAssumption = Truffle.getRuntime().createAssumption("Profiled Argument Types");
-            profiledArgumentTypes = new Class<?>[args.length];
-        } else if (profiledArgumentTypes != null) {
-            if (profiledArgumentTypes.length != args.length) {
-                CompilerDirectives.transferToInterpreter();
-                profiledArgumentTypesAssumption.invalidate();
-                profiledArgumentTypes = null;
-            }
-        }
-
+        profileArguments(args);
         Object result = callBoundary(args);
         Class<?> klass = profiledReturnType;
         if (klass != null && CompilerDirectives.inCompiledCode() && profiledReturnTypeAssumption.isValid()) {
@@ -137,6 +131,66 @@
         return result;
     }
 
+    @ExplodeLoop
+    private void profileArguments(Object[] args) {
+        if (profiledArgumentTypesAssumption == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            initializeProfiledArgumentTypes(args);
+        } else if (profiledArgumentTypes != null) {
+            if (profiledArgumentTypes.length != args.length) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                profiledArgumentTypesAssumption.invalidate();
+                profiledArgumentTypes = null;
+            } else if (TruffleArgumentTypeSpeculation.getValue() && profiledArgumentTypesAssumption.isValid()) {
+                for (int i = 0; i < profiledArgumentTypes.length; i++) {
+                    if (profiledArgumentTypes[i] != null && !profiledArgumentTypes[i].isInstance(args[i])) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        updateProfiledArgumentTypes(args);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    private void initializeProfiledArgumentTypes(Object[] args) {
+        CompilerAsserts.neverPartOfCompilation();
+        profiledArgumentTypesAssumption = Truffle.getRuntime().createAssumption("Profiled Argument Types");
+        profiledArgumentTypes = new Class<?>[args.length];
+        if (TruffleArgumentTypeSpeculation.getValue()) {
+            for (int i = 0; i < args.length; i++) {
+                profiledArgumentTypes[i] = classOf(args[i]);
+            }
+        }
+    }
+
+    private void updateProfiledArgumentTypes(Object[] args) {
+        CompilerAsserts.neverPartOfCompilation();
+        profiledArgumentTypesAssumption.invalidate();
+        for (int j = 0; j < profiledArgumentTypes.length; j++) {
+            profiledArgumentTypes[j] = joinTypes(profiledArgumentTypes[j], classOf(args[j]));
+        }
+        profiledArgumentTypesAssumption = Truffle.getRuntime().createAssumption("Profiled Argument Types");
+    }
+
+    private static Class<?> classOf(Object arg) {
+        return arg != null ? arg.getClass() : null;
+    }
+
+    private static Class<?> joinTypes(Class<?> class1, Class<?> class2) {
+        if (class1 == class2) {
+            return class1;
+        } else if (class1 == null || class2 == null) {
+            return null;
+        } else if (class1.isAssignableFrom(class2)) {
+            return class1;
+        } else if (class2.isAssignableFrom(class1)) {
+            return class2;
+        } else {
+            return Object.class;
+        }
+    }
+
     @TruffleCallBoundary
     private Object callBoundary(Object[] args) {
         if (CompilerDirectives.inInterpreter()) {
@@ -313,10 +367,12 @@
     }
 
     public final Object callRoot(Object[] originalArguments) {
-
         Object[] args = originalArguments;
         if (this.profiledArgumentTypesAssumption != null && CompilerDirectives.inCompiledCode() && profiledArgumentTypesAssumption.isValid()) {
             args = CompilerDirectives.unsafeCast(castArrayFixedLength(args, profiledArgumentTypes.length), Object[].class, true, true);
+            if (TruffleArgumentTypeSpeculation.getValue()) {
+                args = castArguments(args);
+            }
         }
 
         VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), args);
@@ -325,13 +381,13 @@
         // Profile call return type
         if (profiledReturnTypeAssumption == null) {
             if (TruffleReturnTypeSpeculation.getValue()) {
-                CompilerDirectives.transferToInterpreter();
+                CompilerDirectives.transferToInterpreterAndInvalidate();
                 profiledReturnType = (result == null ? null : result.getClass());
                 profiledReturnTypeAssumption = Truffle.getRuntime().createAssumption("Profiled Return Type");
             }
         } else if (profiledReturnType != null) {
             if (result == null || profiledReturnType != result.getClass()) {
-                CompilerDirectives.transferToInterpreter();
+                CompilerDirectives.transferToInterpreterAndInvalidate();
                 profiledReturnType = null;
                 profiledReturnTypeAssumption.invalidate();
             }
@@ -340,6 +396,15 @@
         return result;
     }
 
+    @ExplodeLoop
+    private Object[] castArguments(Object[] originalArguments) {
+        Object[] castArguments = new Object[profiledArgumentTypes.length];
+        for (int i = 0; i < profiledArgumentTypes.length; i++) {
+            castArguments[i] = profiledArgumentTypes[i] != null ? CompilerDirectives.unsafeCast(originalArguments[i], profiledArgumentTypes[i], true, true) : originalArguments[i];
+        }
+        return castArguments;
+    }
+
     private static Object castArrayFixedLength(Object[] args, @SuppressWarnings("unused") int length) {
         return args;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Jul 15 19:21:28 2014 -0700
@@ -124,7 +124,7 @@
             if (TraceTruffleCompilationHistogram.getValue() && constantReceivers != null) {
                 DebugHistogram histogram = Debug.createHistogram("Expanded Truffle Nodes");
                 for (Constant c : constantReceivers) {
-                    String javaName = MetaUtil.toJavaName(providers.getMetaAccess().lookupJavaType(c), false);
+                    String javaName = providers.getMetaAccess().lookupJavaType(c).toJavaName(false);
 
                     // The DSL uses nested classes with redundant names - only show the inner class
                     int index = javaName.indexOf('$');
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Tue Jul 15 19:21:28 2014 -0700
@@ -91,6 +91,8 @@
     public static final OptionValue<Boolean> TruffleCompilationDecisionTimePrintFail = new OptionValue<>(false);
     @Option(help = "")
     public static final OptionValue<Boolean> TruffleReturnTypeSpeculation = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TruffleArgumentTypeSpeculation = new StableOptionValue<>(true);
 
     // tracing
     @Option(help = "")
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleDebugJavaMethod.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleDebugJavaMethod.java	Tue Jul 15 19:21:28 2014 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.truffle;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.truffle.api.*;
@@ -127,6 +125,6 @@
 
     @Override
     public String toString() {
-        return format("Truffle<%n(%p)>", this);
+        return format("Truffle<%n(%p)>");
     }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java	Tue Jul 15 19:21:28 2014 -0700
@@ -25,6 +25,8 @@
 import java.lang.reflect.*;
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
@@ -34,47 +36,27 @@
  */
 public class EffectList implements Iterable<EffectList.Effect> {
 
-    public abstract static class Effect {
-
-        public boolean isVisible() {
+    public interface Effect {
+        default boolean isVisible() {
             return true;
         }
 
-        @Override
-        public String toString() {
-            StringBuilder str = new StringBuilder();
-            for (Field field : getClass().getDeclaredFields()) {
-                String name = field.getName();
-                if (name.contains("$")) {
-                    name = name.substring(name.indexOf('$') + 1);
-                }
-                if (!Modifier.isStatic(field.getModifiers()) && !name.equals("0")) {
-                    try {
-                        field.setAccessible(true);
-                        str.append(str.length() > 0 ? ", " : "").append(name).append("=").append(format(field.get(this)));
-                    } catch (SecurityException | IllegalAccessException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            }
-            return name() + " [" + str + "]";
+        void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes);
+    }
+
+    public interface SimpleEffect extends Effect {
+        default void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
+            apply(graph);
         }
 
-        private static String format(Object object) {
-            if (object != null && Object[].class.isAssignableFrom(object.getClass())) {
-                return Arrays.toString((Object[]) object);
-            }
-            return "" + object;
-        }
-
-        public abstract String name();
-
-        public abstract void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes);
+        void apply(StructuredGraph graph);
     }
 
     private static final Effect[] EMPTY_ARRAY = new Effect[0];
+    private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
     private Effect[] effects = EMPTY_ARRAY;
+    private String[] names = EMPTY_STRING_ARRAY;
     private int size;
 
     private void enlarge(int elements) {
@@ -84,26 +66,31 @@
                 length = Math.max(length * 2, 4);
             }
             effects = Arrays.copyOf(effects, length);
+            if (Debug.isEnabled()) {
+                names = Arrays.copyOf(names, length);
+            }
         }
     }
 
-    public void add(Effect effect) {
-        assert effect != null;
-        enlarge(1);
-        effects[size++] = effect;
+    public void add(String name, SimpleEffect effect) {
+        add(name, (Effect) effect);
     }
 
-    public void addAll(Collection<? extends Effect> list) {
-        enlarge(list.size());
-        for (Effect effect : list) {
-            assert effect != null;
-            effects[size++] = effect;
+    public void add(String name, Effect effect) {
+        assert effect != null;
+        enlarge(1);
+        if (Debug.isEnabled()) {
+            names[size] = name;
         }
+        effects[size++] = effect;
     }
 
     public void addAll(EffectList list) {
         enlarge(list.size);
         System.arraycopy(list.effects, 0, effects, size, list.size);
+        if (Debug.isEnabled()) {
+            System.arraycopy(list.names, 0, names, size, list.size);
+        }
         size += list.size;
     }
 
@@ -112,6 +99,10 @@
         enlarge(list.size);
         System.arraycopy(effects, position, effects, position + list.size, size - position);
         System.arraycopy(list.effects, 0, effects, position, list.size);
+        if (Debug.isEnabled()) {
+            System.arraycopy(names, position, names, position + list.size, size - position);
+            System.arraycopy(list.names, 0, names, position, list.size);
+        }
         size += list.size;
     }
 
@@ -167,15 +158,65 @@
         return size == 0;
     }
 
+    public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
+        for (int i = 0; i < size(); i++) {
+            Effect effect = effects[i];
+            try {
+                effect.apply(graph, obsoleteNodes);
+            } catch (Throwable t) {
+                StringBuilder str = new StringBuilder();
+                toString(str, i);
+                throw new GraalInternalError(t).addContext("effect", str);
+            }
+            if (effect.isVisible() && Debug.isLogEnabled()) {
+                StringBuilder str = new StringBuilder();
+                toString(str, i);
+                Debug.log("    %s", str);
+            }
+        }
+    }
+
+    private void toString(StringBuilder str, int i) {
+        Effect effect = effects[i];
+        str.append(getName(i)).append(" [");
+        boolean first = true;
+        for (Field field : effect.getClass().getDeclaredFields()) {
+            try {
+                field.setAccessible(true);
+                str.append(first ? "" : ", ").append(format(field.get(effect)));
+                first = false;
+            } catch (SecurityException | IllegalAccessException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        str.append(']');
+    }
+
+    private static String format(Object object) {
+        if (object != null && Object[].class.isAssignableFrom(object.getClass())) {
+            return Arrays.toString((Object[]) object);
+        }
+        return "" + object;
+    }
+
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
         for (int i = 0; i < size(); i++) {
             Effect effect = get(i);
             if (effect.isVisible()) {
-                str.append(effect).append('\n');
+                toString(str, i);
+                str.append('\n');
             }
         }
         return str.toString();
     }
+
+    private String getName(int i) {
+        if (Debug.isEnabled()) {
+            return names[i];
+        } else {
+            return "";
+        }
+    }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Tue Jul 15 19:21:28 2014 -0700
@@ -38,12 +38,11 @@
 import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
 import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo;
 import com.oracle.graal.phases.schedule.*;
-import com.oracle.graal.virtual.phases.ea.EffectList.Effect;
 
 public abstract class EffectsClosure<BlockT extends EffectsBlockState<BlockT>> extends EffectsPhase.Closure<BlockT> {
 
-    private final ControlFlowGraph cfg;
-    private final SchedulePhase schedule;
+    protected final ControlFlowGraph cfg;
+    protected final SchedulePhase schedule;
 
     protected final NodeMap<ValueNode> aliases;
     protected final BlockMap<GraphEffectList> blockEffects;
@@ -81,12 +80,7 @@
             private void apply(GraphEffectList effects, Object context) {
                 if (!effects.isEmpty()) {
                     Debug.log(" ==== effects for %s", context);
-                    for (Effect effect : effects) {
-                        effect.apply(graph, obsoleteNodes);
-                        if (effect.isVisible()) {
-                            Debug.log("    %s", effect);
-                        }
-                    }
+                    effects.apply(graph, obsoleteNodes);
                     if (TraceEscapeAnalysis.getValue()) {
                         Debug.dump(graph, EffectsClosure.this.getClass().getSimpleName() + " - after processing %s", context);
                     }
@@ -228,6 +222,11 @@
         @SuppressWarnings("unused")
         protected void commitEnds(List<BlockT> states) {
         }
+
+        @Override
+        public String toString() {
+            return "MergeProcessor@" + merge;
+        }
     }
 
     public void addScalarAlias(ValueNode node, ValueNode alias) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Tue Jul 15 19:21:28 2014 -0700
@@ -26,44 +26,23 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.debug.*;
-import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.common.*;
 
 public class GraphEffectList extends EffectList {
 
     public void addCounterBefore(final String group, final String name, final int increment, final boolean addContext, final FixedNode position) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addCounterBefore";
-            }
+        add("add counter", graph -> DynamicCounterNode.addCounterBefore(group, name, increment, addContext, position));
+    }
 
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert position.isAlive();
-                DynamicCounterNode.addCounterBefore(group, name, increment, addContext, position);
-            }
-        });
+    public void addCounterAfter(final String group, final String name, final int increment, final boolean addContext, final FixedWithNextNode position) {
+        add("add counter after", graph -> DynamicCounterNode.addCounterBefore(group, name, increment, addContext, position.next()));
     }
 
     public void addWeakCounterCounterBefore(final String group, final String name, final int increment, final boolean addContext, final ValueNode checkedValue, final FixedNode position) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addWeakCounterBefore";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert position.isAlive();
-                WeakCounterNode.addCounterBefore(group, name, increment, addContext, checkedValue, position);
-            }
-        });
+        add("add weak counter", graph -> WeakCounterNode.addCounterBefore(group, name, increment, addContext, checkedValue, position));
     }
 
     /**
@@ -74,18 +53,9 @@
      * @param position The fixed node before which the node should be added.
      */
     public void addFixedNodeBefore(final FixedWithNextNode node, final FixedNode position) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addFixedNodeBefore";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert !node.isAlive() && !node.isDeleted() && position.isAlive();
-                graph.addBeforeFixed(position, graph.add(node));
-            }
+        add("add fixed node", graph -> {
+            assert !node.isAlive() && !node.isDeleted() && position.isAlive();
+            graph.addBeforeFixed(position, graph.add(node));
         });
     }
 
@@ -94,20 +64,8 @@
      *
      * @param node The floating node to be added.
      */
-    public void addFloatingNode(final ValueNode node, final String cause) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addFloatingNode " + cause;
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert !node.isAlive() && !node.isDeleted() : node + " " + cause;
-                graph.addWithoutUnique(node);
-            }
-        });
+    public void addFloatingNode(final ValueNode node, @SuppressWarnings("unused") final String cause) {
+        add("add floating node", graph -> graph.addWithoutUnique(node));
     }
 
     /**
@@ -117,18 +75,9 @@
      * @param value The value that will be added to the phi node.
      */
     public void addPhiInput(final PhiNode node, final ValueNode value) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addPhiInput";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert node.isAlive() && value.isAlive() : node + " " + value;
-                node.addInput(value);
-            }
+        add("add phi input", graph -> {
+            assert node.isAlive() && value.isAlive() : node + " " + value;
+            node.addInput(value);
         });
     }
 
@@ -141,18 +90,9 @@
      * @param value The new value for the phi input.
      */
     public void initializePhiInput(final PhiNode node, final int index, final ValueNode value) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "setPhiInput";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert node.isAlive() && value.isAlive() && index >= 0;
-                node.initializeValueAt(index, value);
-            }
+        add("set phi input", (graph, obsoleteNodes) -> {
+            assert node.isAlive() && value.isAlive() && index >= 0;
+            node.initializeValueAt(index, value);
         });
     }
 
@@ -164,13 +104,7 @@
      * @param state The virtual object state to add.
      */
     public void addVirtualMapping(final FrameState node, final EscapeObjectState state) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addVirtualMapping";
-            }
-
+        add("add virtual mapping", new Effect() {
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
                 assert node.isAlive() && !state.isAlive() && !state.isDeleted();
@@ -196,22 +130,19 @@
      * @param node The fixed node that should be deleted.
      */
     public void deleteFixedNode(final FixedWithNextNode node) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "deleteFixedNode";
-            }
+        add("delete fixed node", (graph, obsoleteNodes) -> {
+            GraphUtil.unlinkFixedNode(node);
+            assert obsoleteNodes.add(node);
+        });
+    }
 
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert node.isAlive();
-                FixedNode next = node.next();
-                node.setNext(null);
-                node.replaceAtPredecessor(next);
-                assert obsoleteNodes.add(node);
-            }
-        });
+    /**
+     * Removes the given fixed node from the control flow.
+     *
+     * @param node The fixed node that should be deleted.
+     */
+    public void unlinkFixedNode(final FixedWithNextNode node) {
+        add("unlink fixed node", graph -> GraphUtil.unlinkFixedNode(node));
     }
 
     /**
@@ -225,27 +156,18 @@
      *
      */
     public void replaceAtUsages(final ValueNode node, final ValueNode replacement) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "replaceAtUsages";
+        add("replace at usages", (graph, obsoleteNodes) -> {
+            assert node.isAlive() && replacement.isAlive();
+            if (replacement instanceof FixedWithNextNode && ((FixedWithNextNode) replacement).next() == null) {
+                assert node instanceof FixedNode;
+                graph.addBeforeFixed((FixedNode) node, (FixedWithNextNode) replacement);
             }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert node.isAlive() && replacement.isAlive();
-                if (replacement instanceof FixedWithNextNode && ((FixedWithNextNode) replacement).next() == null) {
-                    assert node instanceof FixedNode;
-                    graph.addBeforeFixed((FixedNode) node, (FixedWithNextNode) replacement);
-                }
-                node.replaceAtUsages(replacement);
-                if (node instanceof FixedWithNextNode) {
-                    FixedNode next = ((FixedWithNextNode) node).next();
-                    ((FixedWithNextNode) node).setNext(null);
-                    node.replaceAtPredecessor(next);
-                    assert obsoleteNodes.add(node);
-                }
+            node.replaceAtUsages(replacement);
+            if (node instanceof FixedWithNextNode) {
+                FixedNode next = ((FixedWithNextNode) node).next();
+                ((FixedWithNextNode) node).setNext(null);
+                node.replaceAtPredecessor(next);
+                assert obsoleteNodes.add(node);
             }
         });
     }
@@ -258,13 +180,7 @@
      * @param newInput The value to replace with.
      */
     public void replaceFirstInput(final Node node, final Node oldInput, final Node newInput) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "replaceFirstInput";
-            }
-
+        add("replace first input", new Effect() {
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
                 assert node.isAlive() && oldInput.isAlive() && newInput.isAlive();
@@ -284,83 +200,6 @@
      * @param action The action that should be performed when the effects are applied.
      */
     public void customAction(final Runnable action) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "customAction";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                action.run();
-            }
-        });
-    }
-
-    /**
-     * Add the materialization node to the graph's control flow at the given position, and then sets
-     * its values.
-     *
-     * @param position The fixed node before which the materialization node should be added.
-     * @param objects The allocated objects.
-     * @param locks The lock depths for each object.
-     * @param values The values (field, elements) of all objects.
-     * @param otherAllocations A list of allocations that need to be added before the rest (used for
-     *            boxing allocations).
-     */
-    public void addMaterializationBefore(final FixedNode position, final List<AllocatedObjectNode> objects, final List<List<MonitorIdNode>> locks, final List<ValueNode> values,
-                    final List<ValueNode> otherAllocations) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addMaterializationBefore";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                for (ValueNode otherAllocation : otherAllocations) {
-                    graph.addWithoutUnique(otherAllocation);
-                    if (otherAllocation instanceof FixedWithNextNode) {
-                        graph.addBeforeFixed(position, (FixedWithNextNode) otherAllocation);
-                    } else {
-                        assert otherAllocation instanceof FloatingNode;
-                    }
-                }
-                if (!objects.isEmpty()) {
-                    CommitAllocationNode commit;
-                    if (position.predecessor() instanceof CommitAllocationNode) {
-                        commit = (CommitAllocationNode) position.predecessor();
-                    } else {
-                        commit = graph.add(new CommitAllocationNode());
-                        graph.addBeforeFixed(position, commit);
-                    }
-                    for (AllocatedObjectNode obj : objects) {
-                        graph.addWithoutUnique(obj);
-                        commit.getVirtualObjects().add(obj.getVirtualObject());
-                        obj.setCommit(commit);
-                    }
-                    commit.getValues().addAll(values);
-                    for (List<MonitorIdNode> monitorIds : locks) {
-                        commit.addLocks(monitorIds);
-                    }
-
-                    assert commit.usages().filter(AllocatedObjectNode.class).count() == commit.usages().count();
-                    List<AllocatedObjectNode> materializedValues = commit.usages().filter(AllocatedObjectNode.class).snapshot();
-                    for (int i = 0; i < commit.getValues().size(); i++) {
-                        if (materializedValues.contains(commit.getValues().get(i))) {
-                            commit.getValues().set(i, ((AllocatedObjectNode) commit.getValues().get(i)).getVirtualObject());
-                        }
-                    }
-
-                }
-            }
-
-            @Override
-            public boolean isVisible() {
-                return true;
-            }
-        });
+        add("customAction", graph -> action.run());
     }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Tue Jul 15 19:21:28 2014 -0700
@@ -120,13 +120,15 @@
     protected void processLoopExit(LoopExitNode exitNode, PEReadEliminationBlockState initialState, PEReadEliminationBlockState exitState, GraphEffectList effects) {
         super.processLoopExit(exitNode, initialState, exitState, effects);
 
-        for (Map.Entry<ReadCacheEntry, ValueNode> entry : exitState.getReadCache().entrySet()) {
-            if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
-                ValueNode value = exitState.getReadCache(entry.getKey().object, entry.getKey().identity, this);
-                if (!(value instanceof ProxyNode) || ((ProxyNode) value).proxyPoint() != exitNode) {
-                    ProxyNode proxy = new ValueProxyNode(value, exitNode);
-                    effects.addFloatingNode(proxy, "readCacheProxy");
-                    entry.setValue(proxy);
+        if (exitNode.graph().hasValueProxies()) {
+            for (Map.Entry<ReadCacheEntry, ValueNode> entry : exitState.getReadCache().entrySet()) {
+                if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
+                    ValueNode value = exitState.getReadCache(entry.getKey().object, entry.getKey().identity, this);
+                    if (!(value instanceof ProxyNode) || ((ProxyNode) value).proxyPoint() != exitNode) {
+                        ProxyNode proxy = new ValueProxyNode(value, exitNode);
+                        effects.addFloatingNode(proxy, "readCacheProxy");
+                        entry.setValue(proxy);
+                    }
                 }
             }
         }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java	Tue Jul 15 19:21:28 2014 -0700
@@ -27,6 +27,7 @@
 import java.util.*;
 
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
 import com.oracle.graal.nodes.virtual.*;
@@ -75,7 +76,42 @@
         List<ValueNode> otherAllocations = new ArrayList<>(2);
         materializeWithCommit(fixed, virtual, objects, locks, values, otherAllocations, state);
 
-        materializeEffects.addMaterializationBefore(fixed, objects, locks, values, otherAllocations);
+        materializeEffects.add("materializeBefore", (graph, obsoleteNodes) -> {
+            for (ValueNode otherAllocation : otherAllocations) {
+                graph.addWithoutUnique(otherAllocation);
+                if (otherAllocation instanceof FixedWithNextNode) {
+                    graph.addBeforeFixed(fixed, (FixedWithNextNode) otherAllocation);
+                } else {
+                    assert otherAllocation instanceof FloatingNode;
+                }
+            }
+            if (!objects.isEmpty()) {
+                CommitAllocationNode commit;
+                if (fixed.predecessor() instanceof CommitAllocationNode) {
+                    commit = (CommitAllocationNode) fixed.predecessor();
+                } else {
+                    commit = graph.add(new CommitAllocationNode());
+                    graph.addBeforeFixed(fixed, commit);
+                }
+                for (AllocatedObjectNode obj : objects) {
+                    graph.addWithoutUnique(obj);
+                    commit.getVirtualObjects().add(obj.getVirtualObject());
+                    obj.setCommit(commit);
+                }
+                commit.getValues().addAll(values);
+                for (List<MonitorIdNode> monitorIds : locks) {
+                    commit.addLocks(monitorIds);
+                }
+
+                assert commit.usages().filter(AllocatedObjectNode.class).count() == commit.usages().count();
+                List<AllocatedObjectNode> materializedValues = commit.usages().filter(AllocatedObjectNode.class).snapshot();
+                for (int i = 0; i < commit.getValues().size(); i++) {
+                    if (materializedValues.contains(commit.getValues().get(i))) {
+                        commit.getValues().set(i, ((AllocatedObjectNode) commit.getValues().get(i)).getVirtualObject());
+                    }
+                }
+            }
+        });
     }
 
     private void materializeWithCommit(FixedNode fixed, VirtualObjectNode virtual, List<AllocatedObjectNode> objects, List<List<MonitorIdNode>> locks, List<ValueNode> values,
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Jul 15 19:21:28 2014 -0700
@@ -229,33 +229,35 @@
                 proxies.put(obj.virtual, proxy);
             }
         }
-        for (ObjectState obj : exitState.getStates()) {
-            ObjectState initialObj = initialState.getObjectStateOptional(obj.virtual);
-            if (obj.isVirtual()) {
-                for (int i = 0; i < obj.getEntries().length; i++) {
-                    ValueNode value = obj.getEntry(i);
-                    if (!(value instanceof VirtualObjectNode || value.isConstant())) {
-                        if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) {
-                            ProxyNode proxy = new ValueProxyNode(value, exitNode);
-                            obj.setEntry(i, proxy);
-                            effects.addFloatingNode(proxy, "virtualProxy");
+        if (exitNode.graph().hasValueProxies()) {
+            for (ObjectState obj : exitState.getStates()) {
+                ObjectState initialObj = initialState.getObjectStateOptional(obj.virtual);
+                if (obj.isVirtual()) {
+                    for (int i = 0; i < obj.getEntries().length; i++) {
+                        ValueNode value = obj.getEntry(i);
+                        if (!(value instanceof VirtualObjectNode || value.isConstant())) {
+                            if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) {
+                                ProxyNode proxy = new ValueProxyNode(value, exitNode);
+                                obj.setEntry(i, proxy);
+                                effects.addFloatingNode(proxy, "virtualProxy");
+                            }
                         }
                     }
-                }
-            } else {
-                if (initialObj == null || initialObj.isVirtual()) {
-                    ProxyNode proxy = proxies.get(obj.virtual);
-                    if (proxy == null) {
-                        proxy = new ValueProxyNode(obj.getMaterializedValue(), exitNode);
-                        effects.addFloatingNode(proxy, "proxy");
+                } else {
+                    if (initialObj == null || initialObj.isVirtual()) {
+                        ProxyNode proxy = proxies.get(obj.virtual);
+                        if (proxy == null) {
+                            proxy = new ValueProxyNode(obj.getMaterializedValue(), exitNode);
+                            effects.addFloatingNode(proxy, "proxy");
+                        } else {
+                            effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
+                            // nothing to do - will be handled in processNode
+                        }
+                        obj.updateMaterializedValue(proxy);
                     } else {
-                        effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
-                        // nothing to do - will be handled in processNode
-                    }
-                    obj.updateMaterializedValue(proxy);
-                } else {
-                    if (initialObj.getMaterializedValue() == obj.getMaterializedValue()) {
-                        Debug.log("materialized value changes within loop: %s vs. %s at %s", initialObj.getMaterializedValue(), obj.getMaterializedValue(), exitNode);
+                        if (initialObj.getMaterializedValue() == obj.getMaterializedValue()) {
+                            Debug.log("materialized value changes within loop: %s vs. %s at %s", initialObj.getMaterializedValue(), obj.getMaterializedValue(), exitNode);
+                        }
                     }
                 }
             }
@@ -457,6 +459,9 @@
                             phis[valueIndex] = new ValuePhiNode(values[valueIndex].stamp().unrestricted(), merge);
                         }
                     }
+                    if (phis[valueIndex] != null && !phis[valueIndex].stamp().isCompatible(values[valueIndex].stamp())) {
+                        phis[valueIndex] = new ValuePhiNode(values[valueIndex].stamp().unrestricted(), merge);
+                    }
                     if (twoSlotKinds != null && twoSlotKinds[valueIndex] != null) {
                         // skip an entry after a long/double value that occupies two int slots
                         valueIndex++;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Tue Jul 15 19:21:28 2014 -0700
@@ -171,11 +171,13 @@
 
     @Override
     protected void processLoopExit(LoopExitNode exitNode, ReadEliminationBlockState initialState, ReadEliminationBlockState exitState, GraphEffectList effects) {
-        for (Map.Entry<CacheEntry<?>, ValueNode> entry : exitState.getReadCache().entrySet()) {
-            if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
-                ProxyNode proxy = new ValueProxyNode(exitState.getCacheEntry(entry.getKey()), exitNode);
-                effects.addFloatingNode(proxy, "readCacheProxy");
-                entry.setValue(proxy);
+        if (exitNode.graph().hasValueProxies()) {
+            for (Map.Entry<CacheEntry<?>, ValueNode> entry : exitState.getReadCache().entrySet()) {
+                if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
+                    ProxyNode proxy = new ValueProxyNode(exitState.getCacheEntry(entry.getKey()), exitNode);
+                    effects.addFloatingNode(proxy, "readCacheProxy");
+                    entry.setValue(proxy);
+                }
             }
         }
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Tue Jul 15 19:21:28 2014 -0700
@@ -120,10 +120,10 @@
         if (filter != null) {
             if (filter.startsWith("~")) {
                 ResolvedJavaMethod method = graph.method();
-                return method == null || !MetaUtil.format("%H.%n", method).contains(filter.substring(1));
+                return method == null || !method.format("%H.%n").contains(filter.substring(1));
             } else {
                 ResolvedJavaMethod method = graph.method();
-                return method != null && MetaUtil.format("%H.%n", method).contains(filter);
+                return method != null && method.format("%H.%n").contains(filter);
             }
         }
         return true;
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -113,6 +113,11 @@
         throw new GraalInternalError("locationIdentity must be a constant so that this node can be canonicalized: " + locationIdentity);
     }
 
+    @Override
+    public IntegerStamp getDisplacementStamp() {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
     @NodeIntrinsic
     public static native Location constantLocation(LocationIdentity identity, Kind kind, long displacement);
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Tue Jul 15 19:21:28 2014 -0700
@@ -114,7 +114,7 @@
                 ValueNode receiver = arguments.get(argc);
                 if (receiver == node && isWord(node)) {
                     ResolvedJavaMethod resolvedMethod = wordAccess.wordImplType.resolveMethod(method, invoke.getContextType());
-                    verify(resolvedMethod != null, node, invoke.asNode(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method));
+                    verify(resolvedMethod != null, node, invoke.asNode(), "cannot resolve method on Word class: " + method.format("%H.%n(%P) %r"));
                     Operation operation = resolvedMethod.getAnnotation(Word.Operation.class);
                     verify(operation != null, node, invoke.asNode(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod);
                 }
@@ -165,7 +165,7 @@
             return buf.toString();
         } else {
             String loc = GraphUtil.approxSourceLocation(n);
-            return loc == null ? MetaUtil.format("method %h.%n", ((StructuredGraph) n.graph()).method()) : loc;
+            return loc == null ? ((StructuredGraph) n.graph()).method().format("method %h.%n") : loc;
         }
     }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,7 +24,6 @@
  */
 package com.oracle.truffle.api.nodes;
 
-import java.io.*;
 import java.lang.annotation.*;
 import java.util.*;
 import java.util.concurrent.*;
@@ -280,9 +279,6 @@
             this.parent.adoptUnadoptedHelper(newNode);
         }
         reportReplace(this, newNode, reason);
-        if (TruffleOptions.TraceASTJSON) {
-            JSONHelper.dumpReplaceChild(this, newNode, reason);
-        }
         onReplace(newNode, reason);
     }
 
@@ -310,6 +306,12 @@
                 ((ReplaceObserver) target).nodeReplaced(oldNode, newNode, reason);
             }
         }
+        if (TruffleOptions.TraceRewrites) {
+            NodeUtil.traceRewrite(this, newNode, reason);
+        }
+        if (TruffleOptions.TraceASTJSON) {
+            JSONHelper.dumpReplaceChild(this, newNode, reason);
+        }
     }
 
     /**
@@ -320,36 +322,7 @@
      * @param reason the reason the replace supplied
      */
     protected void onReplace(Node newNode, CharSequence reason) {
-        if (TruffleOptions.TraceRewrites) {
-            traceRewrite(newNode, reason);
-        }
-    }
-
-    private void traceRewrite(Node newNode, CharSequence reason) {
-        if (TruffleOptions.TraceRewritesFilterFromCost != null) {
-            if (filterByKind(this, TruffleOptions.TraceRewritesFilterFromCost)) {
-                return;
-            }
-        }
-
-        if (TruffleOptions.TraceRewritesFilterToCost != null) {
-            if (filterByKind(newNode, TruffleOptions.TraceRewritesFilterToCost)) {
-                return;
-            }
-        }
-
-        String filter = TruffleOptions.TraceRewritesFilterClass;
-        Class<? extends Node> from = getClass();
-        Class<? extends Node> to = newNode.getClass();
-        if (filter != null && (filterByContainsClassName(from, filter) || filterByContainsClassName(to, filter))) {
-            return;
-        }
-
-        final SourceSection reportedSourceSection = getEncapsulatingSourceSection();
-
-        PrintStream out = System.out;
-        out.printf("[truffle]   rewrite %-50s |From %-40s |To %-40s |Reason %s%s%n", this.toString(), formatNodeInfo(this), formatNodeInfo(newNode), reason != null && reason.length() > 0 ? reason
-                        : "unknown", reportedSourceSection != null ? " at " + reportedSourceSection.getShortDescription() : "");
+        // empty default
     }
 
     /**
@@ -362,43 +335,6 @@
         // empty default
     }
 
-    private static String formatNodeInfo(Node node) {
-        String cost = "?";
-        switch (node.getCost()) {
-            case NONE:
-                cost = "G";
-                break;
-            case MONOMORPHIC:
-                cost = "M";
-                break;
-            case POLYMORPHIC:
-                cost = "P";
-                break;
-            case MEGAMORPHIC:
-                cost = "G";
-                break;
-            default:
-                cost = "?";
-                break;
-        }
-        return cost + " " + node.getClass().getSimpleName();
-    }
-
-    private static boolean filterByKind(Node node, NodeCost cost) {
-        return node.getCost() == cost;
-    }
-
-    private static boolean filterByContainsClassName(Class<? extends Node> from, String filter) {
-        Class<?> currentFrom = from;
-        while (currentFrom != null) {
-            if (currentFrom.getName().contains(filter)) {
-                return false;
-            }
-            currentFrom = currentFrom.getSuperclass();
-        }
-        return true;
-    }
-
     /**
      * Invokes the {@link NodeVisitor#visit(Node)} method for this node and recursively also for all
      * child nodes.
@@ -421,11 +357,9 @@
      * @return the iterator
      */
     public final Iterable<Node> getChildren() {
-        final Node node = this;
         return new Iterable<Node>() {
-
             public Iterator<Node> iterator() {
-                return new NodeUtil.NodeIterator(node);
+                return NodeUtil.makeIterator(Node.this);
             }
         };
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Tue Jul 15 19:21:28 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, 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
@@ -157,8 +157,14 @@
      * every subclass of {@link Node} that is used.
      */
     public static final class NodeClass {
-
-        private static final Map<Class<?>, NodeClass> nodeClasses = new IdentityHashMap<>();
+        private static final ClassValue<NodeClass> nodeClasses = new ClassValue<NodeClass>() {
+            @SuppressWarnings("unchecked")
+            @Override
+            protected NodeClass computeValue(Class<?> clazz) {
+                assert Node.class.isAssignableFrom(clazz);
+                return new NodeClass((Class<? extends Node>) clazz, unsafeFieldOffsetProvider);
+            }
+        };
 
         // The comprehensive list of all fields.
         private final NodeField[] fields;
@@ -166,14 +172,10 @@
         private final long parentOffset;
         private final long[] childOffsets;
         private final long[] childrenOffsets;
+        private final Class<? extends Node> clazz;
 
         public static NodeClass get(Class<? extends Node> clazz) {
-            NodeClass nodeClass = nodeClasses.get(clazz);
-            if (nodeClass == null) {
-                nodeClass = new NodeClass(clazz, unsafeFieldOffsetProvider);
-                nodeClasses.put(clazz, nodeClass);
-            }
-            return nodeClass;
+            return nodeClasses.get(clazz);
         }
 
         public NodeClass(Class<? extends Node> clazz, FieldOffsetProvider fieldOffsetProvider) {
@@ -209,6 +211,7 @@
             this.parentOffset = parentOffsetsList.get(0);
             this.childOffsets = toLongArray(childOffsetsList);
             this.childrenOffsets = toLongArray(childrenOffsetsList);
+            this.clazz = clazz;
         }
 
         public NodeField[] getFields() {
@@ -241,73 +244,71 @@
             }
             return false;
         }
-    }
 
-    static class NodeIterator implements Iterator<Node> {
-
-        private final Node node;
-        private final NodeClass nodeClass;
-        private final int childrenCount;
-        private int index;
-
-        protected NodeIterator(Node node) {
-            this.node = node;
-            this.index = 0;
-            this.nodeClass = NodeClass.get(node.getClass());
-            this.childrenCount = childrenCount();
-        }
-
-        private int childrenCount() {
-            int nodeCount = nodeClass.childOffsets.length;
-            for (long fieldOffset : nodeClass.childrenOffsets) {
-                Node[] children = ((Node[]) unsafe.getObject(node, fieldOffset));
-                if (children != null) {
-                    nodeCount += children.length;
-                }
-            }
-            return nodeCount;
+        public Iterator<Node> makeIterator(Node node) {
+            assert clazz.isInstance(node);
+            return new NodeIterator(node);
         }
 
-        private Node nodeAt(int idx) {
-            int nodeCount = nodeClass.childOffsets.length;
-            if (idx < nodeCount) {
-                return (Node) unsafe.getObject(node, nodeClass.childOffsets[idx]);
-            } else {
-                for (long fieldOffset : nodeClass.childrenOffsets) {
-                    Node[] nodeArray = (Node[]) unsafe.getObject(node, fieldOffset);
-                    if (idx < nodeCount + nodeArray.length) {
-                        return nodeArray[idx - nodeCount];
+        private final class NodeIterator implements Iterator<Node> {
+            private final Node node;
+            private int fieldIndex;
+            private int arrayIndex;
+
+            protected NodeIterator(Node node) {
+                this.node = node;
+            }
+
+            private void forward() {
+                if (fieldIndex < childOffsets.length) {
+                    fieldIndex++;
+                } else if (fieldIndex < childOffsets.length + childrenOffsets.length) {
+                    if (arrayIndex + 1 < currentChildrenArrayLength()) {
+                        arrayIndex++;
+                    } else {
+                        arrayIndex = 0;
+                        do {
+                            fieldIndex++;
+                        } while (fieldIndex < childOffsets.length + childrenOffsets.length && currentChildrenArrayLength() == 0);
                     }
-                    nodeCount += nodeArray.length;
                 }
             }
-            return null;
-        }
+
+            public boolean hasNext() {
+                return fieldIndex < childOffsets.length || (fieldIndex < childOffsets.length + childrenOffsets.length && arrayIndex < currentChildrenArrayLength());
+            }
+
+            private Node[] currentChildrenArray() {
+                assert fieldIndex >= childOffsets.length && fieldIndex < childOffsets.length + childrenOffsets.length;
+                return (Node[]) unsafe.getObject(node, childrenOffsets[fieldIndex - childOffsets.length]);
+            }
+
+            private int currentChildrenArrayLength() {
+                Node[] childrenArray = currentChildrenArray();
+                return childrenArray != null ? childrenArray.length : 0;
+            }
 
-        private void forward() {
-            if (index < childrenCount) {
-                index++;
+            public Node next() {
+                Node next;
+                if (fieldIndex < childOffsets.length) {
+                    next = (Node) unsafe.getObject(node, childOffsets[fieldIndex]);
+                } else if (fieldIndex < childOffsets.length + childrenOffsets.length) {
+                    next = currentChildrenArray()[arrayIndex];
+                } else {
+                    throw new NoSuchElementException();
+                }
+                forward();
+                return next;
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException();
             }
         }
-
-        @Override
-        public boolean hasNext() {
-            return index < childrenCount;
-        }
+    }
 
-        @Override
-        public Node next() {
-            try {
-                return nodeAt(index);
-            } finally {
-                forward();
-            }
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
+    static Iterator<Node> makeIterator(Node node) {
+        return NodeClass.get(node.getClass()).makeIterator(node);
     }
 
     private static long[] toLongArray(List<Long> list) {
@@ -542,15 +543,12 @@
         return null;
     }
 
-    public static <T extends Node> List<T> findAllNodeInstances(final Node root, final Class<T> clazz) {
+    public static <T> List<T> findAllNodeInstances(final Node root, final Class<T> clazz) {
         final List<T> nodeList = new ArrayList<>();
         root.accept(new NodeVisitor() {
-
-            @SuppressWarnings("unchecked")
-            @Override
             public boolean visit(Node node) {
                 if (clazz.isInstance(node)) {
-                    nodeList.add((T) node);
+                    nodeList.add(clazz.cast(node));
                 }
                 return true;
             }
@@ -558,53 +556,15 @@
         return nodeList;
     }
 
-    // Don't visit found node instances.
-    public static <T extends Node> List<T> findNodeInstancesShallow(final Node root, final Class<T> clazz) {
-        final List<T> nodeList = new ArrayList<>();
-        root.accept(new NodeVisitor() {
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public boolean visit(Node node) {
-                if (clazz.isInstance(node)) {
-                    nodeList.add((T) node);
-                    return false;
-                }
-                return true;
-            }
-        });
-        return nodeList;
-    }
-
-    /** Find node instances within current function only (not in nested functions). */
-    public static <T extends Node> List<T> findNodeInstancesInFunction(final Node root, final Class<T> clazz) {
+    /**
+     * Like {@link #findAllNodeInstances(Node, Class)} but do not visit children of found nodes.
+     */
+    public static <T> List<T> findNodeInstancesShallow(final Node root, final Class<T> clazz) {
         final List<T> nodeList = new ArrayList<>();
         root.accept(new NodeVisitor() {
-
-            @SuppressWarnings("unchecked")
-            @Override
             public boolean visit(Node node) {
                 if (clazz.isInstance(node)) {
-                    nodeList.add((T) node);
-                } else if (node instanceof RootNode && node != root) {
-                    return false;
-                }
-                return true;
-            }
-        });
-        return nodeList;
-    }
-
-    public static <I> List<I> findNodeInstancesInFunctionInterface(final Node root, final Class<I> clazz) {
-        final List<I> nodeList = new ArrayList<>();
-        root.accept(new NodeVisitor() {
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public boolean visit(Node node) {
-                if (clazz.isInstance(node)) {
-                    nodeList.add((I) node);
-                } else if (node instanceof RootNode && node != root) {
+                    nodeList.add(clazz.cast(node));
                     return false;
                 }
                 return true;
@@ -864,6 +824,9 @@
 
     private static String displaySourceAttribution(Node node) {
         final SourceSection section = node.getSourceSection();
+        if (section instanceof NullSourceSection) {
+            return "source: " + section.getShortDescription();
+        }
         if (section != null) {
             final String srcText = section.getCode();
             final StringBuilder sb = new StringBuilder();
@@ -891,4 +854,68 @@
     private static String toStringWithClass(Object obj) {
         return obj == null ? "null" : obj + "(" + obj.getClass().getName() + ")";
     }
+
+    static void traceRewrite(Node oldNode, Node newNode, CharSequence reason) {
+        if (TruffleOptions.TraceRewritesFilterFromCost != null) {
+            if (filterByKind(oldNode, TruffleOptions.TraceRewritesFilterFromCost)) {
+                return;
+            }
+        }
+
+        if (TruffleOptions.TraceRewritesFilterToCost != null) {
+            if (filterByKind(newNode, TruffleOptions.TraceRewritesFilterToCost)) {
+                return;
+            }
+        }
+
+        String filter = TruffleOptions.TraceRewritesFilterClass;
+        Class<? extends Node> from = oldNode.getClass();
+        Class<? extends Node> to = newNode.getClass();
+        if (filter != null && (filterByContainsClassName(from, filter) || filterByContainsClassName(to, filter))) {
+            return;
+        }
+
+        final SourceSection reportedSourceSection = oldNode.getEncapsulatingSourceSection();
+
+        PrintStream out = System.out;
+        out.printf("[truffle]   rewrite %-50s |From %-40s |To %-40s |Reason %s%s%n", oldNode.toString(), formatNodeInfo(oldNode), formatNodeInfo(newNode),
+                        reason != null && reason.length() > 0 ? reason : "unknown", reportedSourceSection != null ? " at " + reportedSourceSection.getShortDescription() : "");
+    }
+
+    private static String formatNodeInfo(Node node) {
+        String cost = "?";
+        switch (node.getCost()) {
+            case NONE:
+                cost = "G";
+                break;
+            case MONOMORPHIC:
+                cost = "M";
+                break;
+            case POLYMORPHIC:
+                cost = "P";
+                break;
+            case MEGAMORPHIC:
+                cost = "G";
+                break;
+            default:
+                cost = "?";
+                break;
+        }
+        return cost + " " + node.getClass().getSimpleName();
+    }
+
+    private static boolean filterByKind(Node node, NodeCost cost) {
+        return node.getCost() == cost;
+    }
+
+    private static boolean filterByContainsClassName(Class<? extends Node> from, String filter) {
+        Class<?> currentFrom = from;
+        while (currentFrom != null) {
+            if (currentFrom.getName().contains(filter)) {
+                return false;
+            }
+            currentFrom = currentFrom.getSuperclass();
+        }
+        return true;
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java	Tue Jul 15 19:21:28 2014 -0700
@@ -122,15 +122,15 @@
         AstJsonDumpBuilder = new StringBuilder();
     }
 
-    public static JsonObjectBuilder object() {
-        return new JsonObjectBuilder();
+    public static JSONObjectBuilder object() {
+        return new JSONObjectBuilder();
     }
 
-    public static JsonArrayBuilder array() {
-        return new JsonArrayBuilder();
+    public static JSONArrayBuilder array() {
+        return new JSONArrayBuilder();
     }
 
-    public static abstract class JsonStringBuilder {
+    public static abstract class JSONStringBuilder {
         @Override
         public final String toString() {
             StringBuilder sb = new StringBuilder();
@@ -141,8 +141,8 @@
         protected abstract void appendTo(StringBuilder sb);
 
         protected static void appendValue(StringBuilder sb, Object value) {
-            if (value instanceof JsonStringBuilder) {
-                ((JsonStringBuilder) value).appendTo(sb);
+            if (value instanceof JSONStringBuilder) {
+                ((JSONStringBuilder) value).appendTo(sb);
             } else if (value instanceof Integer || value instanceof Boolean || value == null) {
                 sb.append(value);
             } else {
@@ -151,28 +151,28 @@
         }
     }
 
-    public static final class JsonObjectBuilder extends JsonStringBuilder {
+    public static final class JSONObjectBuilder extends JSONStringBuilder {
         private final Map<String, Object> contents = new LinkedHashMap<>();
 
-        private JsonObjectBuilder() {
+        private JSONObjectBuilder() {
         }
 
-        public JsonObjectBuilder add(String key, String value) {
+        public JSONObjectBuilder add(String key, String value) {
             contents.put(key, value);
             return this;
         }
 
-        public JsonObjectBuilder add(String key, Number value) {
+        public JSONObjectBuilder add(String key, Number value) {
             contents.put(key, value);
             return this;
         }
 
-        public JsonObjectBuilder add(String key, Boolean value) {
+        public JSONObjectBuilder add(String key, Boolean value) {
             contents.put(key, value);
             return this;
         }
 
-        public JsonObjectBuilder add(String key, JsonStringBuilder value) {
+        public JSONObjectBuilder add(String key, JSONStringBuilder value) {
             contents.put(key, value);
             return this;
         }
@@ -194,28 +194,28 @@
         }
     }
 
-    public static final class JsonArrayBuilder extends JsonStringBuilder {
+    public static final class JSONArrayBuilder extends JSONStringBuilder {
         private final List<Object> contents = new ArrayList<>();
 
-        private JsonArrayBuilder() {
+        private JSONArrayBuilder() {
         }
 
-        public JsonArrayBuilder add(String value) {
+        public JSONArrayBuilder add(String value) {
             contents.add(value);
             return this;
         }
 
-        public JsonArrayBuilder add(Number value) {
+        public JSONArrayBuilder add(Number value) {
             contents.add(value);
             return this;
         }
 
-        public JsonArrayBuilder add(Boolean value) {
+        public JSONArrayBuilder add(Boolean value) {
             contents.add(value);
             return this;
         }
 
-        public JsonArrayBuilder add(JsonStringBuilder value) {
+        public JSONArrayBuilder add(JSONStringBuilder value) {
             contents.add(value);
             return this;
         }
--- a/graal/com.oracle.truffle.sl.test/tests/String.output	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl.test/tests/String.output	Tue Jul 15 19:21:28 2014 -0700
@@ -7,4 +7,4 @@
 bars
 foos
 2 < 4: true
-Type error at String.sl line 9 col 36: operation "<" not defined for Number 2, String "4"
+Type error at String.sl line 9 col 34: operation "<" not defined for Number 2, String "4"
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError01.output	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl.test/tests/error/TypeError01.output	Tue Jul 15 19:21:28 2014 -0700
@@ -1,1 +1,1 @@
-Type error at TypeError01.sl line 2 col 5: operation "-" not defined for Number 3, String "4"
+Type error at TypeError01.sl line 2 col 3: operation "-" not defined for Number 3, String "4"
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError03.output	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl.test/tests/error/TypeError03.output	Tue Jul 15 19:21:28 2014 -0700
@@ -1,1 +1,1 @@
-Type error at TypeError03.sl line 2 col 7: operation "&&" not defined for String "4", ANY
+Type error at TypeError03.sl line 2 col 3: operation "&&" not defined for String "4", ANY
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError04.output	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl.test/tests/error/TypeError04.output	Tue Jul 15 19:21:28 2014 -0700
@@ -1,1 +1,1 @@
-Type error at TypeError04.sl line 2 col 11: operation "||" not defined for Boolean false, Number 4
+Type error at TypeError04.sl line 2 col 4: operation "||" not defined for Boolean false, Number 4
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Tue Jul 15 19:21:28 2014 -0700
@@ -143,6 +143,7 @@
     public static void run(SLContext context, Source source, PrintStream logOutput, int repeats) {
         if (logOutput != null) {
             logOutput.println("== running on " + Truffle.getRuntime().getName());
+            // logOutput.println("Source = " + source.getCode());
         }
 
         final SourceCallback sourceCallback = context.getSourceCallback();
@@ -163,10 +164,12 @@
 
         /* Change to true if you want to see the AST on the console. */
         boolean printASTToLog = false;
+        /* Change to true if you want to see source attribution for the AST to the console */
+        boolean printSourceAttributionToLog = false;
         /* Change to dump the AST to IGV over the network. */
         boolean dumpASTToIGV = false;
 
-        printScript("before execution", context, logOutput, printASTToLog, dumpASTToIGV);
+        printScript("before execution", context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV);
         try {
             for (int i = 0; i < repeats; i++) {
                 long start = System.nanoTime();
@@ -187,7 +190,7 @@
             }
 
         } finally {
-            printScript("after execution", context, logOutput, printASTToLog, dumpASTToIGV);
+            printScript("after execution", context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV);
         }
     }
 
@@ -197,7 +200,7 @@
      * <p>
      * When printASTToLog is true: prints the ASTs to the console.
      */
-    private static void printScript(String groupName, SLContext context, PrintStream logOutput, boolean printASTToLog, boolean dumpASTToIGV) {
+    private static void printScript(String groupName, SLContext context, PrintStream logOutput, boolean printASTToLog, boolean printSourceAttributionToLog, boolean dumpASTToIGV) {
         if (dumpASTToIGV) {
             GraphPrintVisitor graphPrinter = new GraphPrintVisitor();
             graphPrinter.beginGroup(groupName);
@@ -218,6 +221,15 @@
                 }
             }
         }
+        if (printSourceAttributionToLog && logOutput != null) {
+            for (SLFunction function : context.getFunctionRegistry().getFunctions()) {
+                RootCallTarget callTarget = function.getCallTarget();
+                if (callTarget != null) {
+                    logOutput.println("=== " + function);
+                    NodeUtil.printSourceAttributionTree(logOutput, callTarget.getRootNode());
+                }
+            }
+        }
     }
 
     /**
@@ -233,7 +245,9 @@
         result.append("Type error");
         if (ex.getNode() != null && ex.getNode().getSourceSection() != null) {
             SourceSection ss = ex.getNode().getSourceSection();
-            result.append(" at ").append(ss.getSource().getName()).append(" line ").append(ss.getStartLine()).append(" col ").append(ss.getStartColumn());
+            if (ss != null && !(ss instanceof NullSourceSection)) {
+                result.append(" at ").append(ss.getSource().getName()).append(" line ").append(ss.getStartLine()).append(" col ").append(ss.getStartColumn());
+            }
         }
         result.append(": operation");
         if (ex.getNode() != null && ex.getNode().getClass().getAnnotation(NodeInfo.class) != null) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLBuiltinNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLBuiltinNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.truffle.sl.builtins;
 
 import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
@@ -42,6 +43,10 @@
 @NodeField(name = "context", type = SLContext.class)
 public abstract class SLBuiltinNode extends SLExpressionNode {
 
+    public SLBuiltinNode(SourceSection src) {
+        super(src);
+    }
+
     /**
      * Accessor for the {@link SLContext}. The implementation of this method is generated
      * automatically based on the {@link NodeField} annotation on the class.
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java	Tue Jul 15 19:21:28 2014 -0700
@@ -36,6 +36,10 @@
 @NodeInfo(shortName = "defineFunction")
 public abstract class SLDefineFunctionBuiltin extends SLBuiltinNode {
 
+    public SLDefineFunctionBuiltin() {
+        super(new NullSourceSection("SL builtin", "defineFunction"));
+    }
+
     @Specialization
     public String defineFunction(String code) {
         doDefineFunction(getContext(), code);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java	Tue Jul 15 19:21:28 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 
 /**
  * This builtin sets the variable named "hello" in the caller frame to the string "world".
@@ -34,6 +35,10 @@
 @NodeInfo(shortName = "helloEqualsWorld")
 public abstract class SLHelloEqualsWorldBuiltin extends SLBuiltinNode {
 
+    public SLHelloEqualsWorldBuiltin() {
+        super(new NullSourceSection("SL builtin", "helloEqualsWorld"));
+    }
+
     @Specialization
     public String change() {
         FrameInstance frameInstance = Truffle.getRuntime().getStackTrace().iterator().next();
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNanoTimeBuiltin.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNanoTimeBuiltin.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 
 /**
  * Builtin function that returns the value of a high-resolution time, in nanoseconds.
@@ -31,6 +32,10 @@
 @NodeInfo(shortName = "nanoTime")
 public abstract class SLNanoTimeBuiltin extends SLBuiltinNode {
 
+    public SLNanoTimeBuiltin() {
+        super(new NullSourceSection("SL builtin", "nanoTime"));
+    }
+
     @Specialization
     public long nanoTime() {
         return System.nanoTime();
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLPrintlnBuiltin.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLPrintlnBuiltin.java	Tue Jul 15 19:21:28 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.truffle.api.CompilerDirectives.SlowPath;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.runtime.*;
 
 /**
@@ -41,6 +42,10 @@
 @NodeInfo(shortName = "println")
 public abstract class SLPrintlnBuiltin extends SLBuiltinNode {
 
+    public SLPrintlnBuiltin() {
+        super(new NullSourceSection("SL builtin", "println"));
+    }
+
     @Specialization
     public long println(long value) {
         doPrint(getContext().getOutput(), value);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLReadlnBuiltin.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLReadlnBuiltin.java	Tue Jul 15 19:21:28 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.truffle.api.CompilerDirectives.SlowPath;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.*;
 import com.oracle.truffle.sl.runtime.*;
 
@@ -36,6 +37,10 @@
 @NodeInfo(shortName = "readln")
 public abstract class SLReadlnBuiltin extends SLBuiltinNode {
 
+    public SLReadlnBuiltin() {
+        super(new NullSourceSection("SL builtin", "readln"));
+    }
+
     @Specialization
     public String readln() {
         String result = doRead(getContext().getInput());
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java	Tue Jul 15 19:21:28 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 
 /**
  * Returns a string representation of the current stack. This includes the {@link CallTarget}s and
@@ -37,6 +38,10 @@
 @NodeInfo(shortName = "stacktrace")
 public abstract class SLStackTraceBuiltin extends SLBuiltinNode {
 
+    public SLStackTraceBuiltin() {
+        super(new NullSourceSection("SL builtin", "stacktrace"));
+    }
+
     @Specialization
     public String trace() {
         return createStackTrace();
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLBinaryNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLBinaryNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.truffle.sl.nodes;
 
 import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.source.*;
 
 /**
  * Utility base class for operations that take two arguments (per convention called "left" and
@@ -31,4 +32,8 @@
  */
 @NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")})
 public abstract class SLBinaryNode extends SLExpressionNode {
+
+    public SLBinaryNode(SourceSection src) {
+        super(src);
+    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.runtime.*;
 
 /**
@@ -38,6 +39,10 @@
 @NodeInfo(description = "The abstract base node for all expressions")
 public abstract class SLExpressionNode extends SLStatementNode {
 
+    public SLExpressionNode(SourceSection src) {
+        super(src);
+    }
+
     /**
      * The execute method when no specialization is possible. This is the most general case,
      * therefore it must be provided by all subclasses.
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 
 /**
  * The base class of all Truffle nodes for SL. All nodes (even expressions) can be used as
@@ -33,6 +34,10 @@
 @NodeInfo(language = "Simple Language", description = "The abstract base node for all statements")
 public abstract class SLStatementNode extends Node {
 
+    public SLStatementNode(SourceSection src) {
+        super(src);
+    }
+
     /**
      * Execute this node as as statement, where no return value is necessary.
      */
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
@@ -39,15 +40,16 @@
 @NodeInfo(shortName = "invoke")
 public final class SLInvokeNode extends SLExpressionNode {
 
-    public static SLInvokeNode create(SLExpressionNode function, SLExpressionNode[] arguments) {
-        return new SLInvokeNode(function, arguments, new SLUninitializedDispatchNode());
+    public static SLInvokeNode create(SourceSection src, SLExpressionNode function, SLExpressionNode[] arguments) {
+        return new SLInvokeNode(src, function, arguments, new SLUninitializedDispatchNode());
     }
 
     @Child protected SLExpressionNode functionNode;
     @Children protected final SLExpressionNode[] argumentNodes;
     @Child protected SLAbstractDispatchNode dispatchNode;
 
-    private SLInvokeNode(SLExpressionNode functionNode, SLExpressionNode[] argumentNodes, SLAbstractDispatchNode dispatchNode) {
+    private SLInvokeNode(SourceSection src, SLExpressionNode functionNode, SLExpressionNode[] argumentNodes, SLAbstractDispatchNode dispatchNode) {
+        super(src);
         this.functionNode = functionNode;
         this.argumentNodes = argumentNodes;
         this.dispatchNode = dispatchNode;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -40,7 +41,8 @@
      */
     @Children private final SLStatementNode[] bodyNodes;
 
-    public SLBlockNode(SLStatementNode[] bodyNodes) {
+    public SLBlockNode(SourceSection src, SLStatementNode[] bodyNodes) {
+        super(src);
         this.bodyNodes = bodyNodes;
     }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -35,6 +36,10 @@
 @NodeInfo(shortName = "break", description = "The node implementing a break statement")
 public final class SLBreakNode extends SLStatementNode {
 
+    public SLBreakNode(SourceSection src) {
+        super(src);
+    }
+
     @Override
     public void executeVoid(VirtualFrame frame) {
         throw SLBreakException.SINGLETON;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -35,6 +36,10 @@
 @NodeInfo(shortName = "continue", description = "The node implementing a continue statement")
 public final class SLContinueNode extends SLStatementNode {
 
+    public SLContinueNode(SourceSection src) {
+        super(src);
+    }
+
     @Override
     public void executeVoid(VirtualFrame frame) {
         throw SLContinueException.SINGLETON;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -29,7 +29,7 @@
 import com.oracle.truffle.sl.runtime.*;
 
 /**
- * The body of a user-defined SL function. This is the node references by a {@link SLRootNode} for
+ * The body of a user-defined SL function. This is the node referenced by a {@link SLRootNode} for
  * user-defined functions. It handles the return value of a function: the {@link SLReturnNode return
  * statement} throws an {@link SLReturnException exception} with the return value. This node catches
  * the exception. If the method ends without an explicit {@code return}, return the
@@ -50,6 +50,7 @@
     private final BranchProfile nullTaken = new BranchProfile();
 
     public SLFunctionBodyNode(SLStatementNode bodyNode) {
+        super(null);
         this.bodyNode = bodyNode;
     }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.sl.nodes.*;
 
@@ -52,7 +53,8 @@
     private final BranchProfile thenTaken = new BranchProfile();
     private final BranchProfile elseTaken = new BranchProfile();
 
-    public SLIfNode(SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
+    public SLIfNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
+        super(src);
         this.conditionNode = conditionNode;
         this.thenPartNode = thenPartNode;
         this.elsePartNode = elsePartNode;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
@@ -39,7 +40,8 @@
 
     @Child private SLExpressionNode valueNode;
 
-    public SLReturnNode(SLExpressionNode valueNode) {
+    public SLReturnNode(SourceSection src, SLExpressionNode valueNode) {
+        super(src);
         this.valueNode = valueNode;
     }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.sl.nodes.*;
 
@@ -50,7 +51,8 @@
     private final BranchProfile continueTaken = new BranchProfile();
     private final BranchProfile breakTaken = new BranchProfile();
 
-    public SLWhileNode(SLExpressionNode conditionNode, SLStatementNode bodyNode) {
+    public SLWhileNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
+        super(src);
         this.conditionNode = conditionNode;
         this.bodyNode = bodyNode;
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -42,6 +43,10 @@
 @NodeInfo(shortName = "+")
 public abstract class SLAddNode extends SLBinaryNode {
 
+    public SLAddNode(SourceSection src) {
+        super(src);
+    }
+
     /**
      * Specialization for primitive {@code long} values. This is the fast path of the
      * arbitrary-precision arithmetic. We need to check for overflows of the addition, and switch to
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLBigIntegerLiteralNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLBigIntegerLiteralNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -26,6 +26,7 @@
 
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -37,7 +38,8 @@
 
     private final BigInteger value;
 
-    public SLBigIntegerLiteralNode(BigInteger value) {
+    public SLBigIntegerLiteralNode(SourceSection src, BigInteger value) {
+        super(src);
         this.value = value;
     }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLDivNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLDivNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -26,6 +26,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -36,6 +37,10 @@
 @NodeInfo(shortName = "/")
 public abstract class SLDivNode extends SLBinaryNode {
 
+    public SLDivNode(SourceSection src) {
+        super(src);
+    }
+
     @Specialization
     protected long div(long left, long right) {
         /* No overflow is possible on a division. */
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -26,6 +26,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
@@ -42,6 +43,10 @@
 @NodeInfo(shortName = "==")
 public abstract class SLEqualNode extends SLBinaryNode {
 
+    public SLEqualNode(SourceSection src) {
+        super(src);
+    }
+
     @Specialization
     protected boolean equal(long left, long right) {
         return left == right;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
@@ -39,7 +40,8 @@
 
     private final SLFunction value;
 
-    public SLFunctionLiteralNode(SLFunction value) {
+    public SLFunctionLiteralNode(SourceSection src, SLFunction value) {
+        super(src);
         this.value = value;
     }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessOrEqualNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessOrEqualNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -26,6 +26,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -34,6 +35,10 @@
 @NodeInfo(shortName = "<=")
 public abstract class SLLessOrEqualNode extends SLBinaryNode {
 
+    public SLLessOrEqualNode(SourceSection src) {
+        super(src);
+    }
+
     @Specialization
     protected boolean lessOrEqual(long left, long right) {
         return left <= right;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessThanNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessThanNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -26,6 +26,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -35,6 +36,10 @@
 @NodeInfo(shortName = "<")
 public abstract class SLLessThanNode extends SLBinaryNode {
 
+    public SLLessThanNode(SourceSection src) {
+        super(src);
+    }
+
     @Specialization
     protected boolean lessThan(long left, long right) {
         return left < right;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalAndNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalAndNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -39,6 +40,10 @@
 @SuppressWarnings("unused")
 public abstract class SLLogicalAndNode extends SLBinaryNode {
 
+    public SLLogicalAndNode(SourceSection src) {
+        super(src);
+    }
+
     /**
      * This method is called after the left child was evaluated, but before the right child is
      * evaluated. The right child is only evaluated when the return value is {code true}.
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalNotNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalNotNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -34,6 +35,10 @@
 @NodeInfo(shortName = "!")
 public abstract class SLLogicalNotNode extends SLExpressionNode {
 
+    public SLLogicalNotNode(SourceSection src) {
+        super(src);
+    }
+
     @Specialization
     protected boolean doBoolean(boolean value) {
         return !value;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalOrNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalOrNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -33,6 +34,10 @@
 @SuppressWarnings("unused")
 public abstract class SLLogicalOrNode extends SLBinaryNode {
 
+    public SLLogicalOrNode(SourceSection src) {
+        super(src);
+    }
+
     @ShortCircuit("rightNode")
     protected boolean needsRightNode(boolean left) {
         return !left;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLongLiteralNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLongLiteralNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -36,7 +37,8 @@
 
     private final long value;
 
-    public SLLongLiteralNode(long value) {
+    public SLLongLiteralNode(SourceSection src, long value) {
+        super(src);
         this.value = value;
     }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLMulNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLMulNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.truffle.api.CompilerDirectives.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -36,6 +37,10 @@
 @NodeInfo(shortName = "*")
 public abstract class SLMulNode extends SLBinaryNode {
 
+    public SLMulNode(SourceSection src) {
+        super(src);
+    }
+
     @Specialization(rewriteOn = ArithmeticException.class)
     protected long mul(long left, long right) {
         return ExactMath.multiplyExact(left, right);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLStringLiteralNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLStringLiteralNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -34,7 +35,8 @@
 
     private final String value;
 
-    public SLStringLiteralNode(String value) {
+    public SLStringLiteralNode(SourceSection src, String value) {
+        super(src);
         this.value = value;
     }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLSubNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLSubNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -35,6 +36,10 @@
 @NodeInfo(shortName = "-")
 public abstract class SLSubNode extends SLBinaryNode {
 
+    public SLSubNode(SourceSection src) {
+        super(src);
+    }
+
     @Specialization(rewriteOn = ArithmeticException.class)
     protected long sub(long left, long right) {
         return ExactMath.subtractExact(left, right);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/demo/SLAddWithoutSpecializationNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/demo/SLAddWithoutSpecializationNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -42,6 +42,7 @@
     @Child private SLExpressionNode rightNode;
 
     public SLAddWithoutSpecializationNode(SLExpressionNode leftNode, SLExpressionNode rightNode) {
+        super(null);
         this.leftNode = leftNode;
         this.rightNode = rightNode;
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadArgumentNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadArgumentNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.truffle.sl.nodes.local;
 
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.parser.*;
@@ -46,7 +47,8 @@
      */
     private final BranchProfile outOfBoundsTaken = new BranchProfile();
 
-    public SLReadArgumentNode(int index) {
+    public SLReadArgumentNode(SourceSection src, int index) {
+        super(src);
         this.index = index;
     }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -36,6 +37,10 @@
 @NodeField(name = "slot", type = FrameSlot.class)
 public abstract class SLReadLocalVariableNode extends SLExpressionNode {
 
+    public SLReadLocalVariableNode(SourceSection src) {
+        super(src);
+    }
+
     /**
      * Returns the descriptor of the accessed local variable. The implementation of this method is
      * created by the Truffle DSL based on the {@link NodeField} annotation on the class.
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java	Tue Jul 15 19:21:28 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
 
 /**
@@ -35,6 +36,10 @@
 @NodeField(name = "slot", type = FrameSlot.class)
 public abstract class SLWriteLocalVariableNode extends SLExpressionNode {
 
+    public SLWriteLocalVariableNode(SourceSection src) {
+        super(src);
+    }
+
     /**
      * Returns the descriptor of the accessed local variable. The implementation of this method is
      * created by the Truffle DSL based on the {@link NodeField} annotation on the class.
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Tue Jul 15 19:21:28 2014 -0700
@@ -52,7 +52,7 @@
     public final Scanner scanner;
     public final Errors errors;
     private final SLNodeFactory factory;
-
+    
     public Parser(SLContext context, Source source) {
         this.scanner = new Scanner(source.getInputStream());
         this.factory = new SLNodeFactory(context, source);
@@ -133,39 +133,41 @@
 	void Function() {
 		Expect(4);
 		Expect(1);
-		factory.startFunction(t);
+		factory.startFunction(t); 
 		Expect(5);
 		if (la.kind == 1) {
 			Get();
-			factory.addFormalParameter(t);
+			factory.addFormalParameter(t); 
 			while (la.kind == 6) {
 				Get();
 				Expect(1);
-				factory.addFormalParameter(t);
+				factory.addFormalParameter(t); 
 			}
 		}
 		Expect(7);
 		SLStatementNode body = Block(false);
-		factory.finishFunction(body);
+		factory.finishFunction(body); 
 	}
 
 	SLStatementNode  Block(boolean inLoop) {
 		SLStatementNode  result;
 		factory.startBlock();
-		List<SLStatementNode> body = new ArrayList<>();
+		List<SLStatementNode> body = new ArrayList<>(); 
 		Expect(8);
+		int lBracePos = t.charPos; 
 		while (StartOf(1)) {
 			SLStatementNode s = Statement(inLoop);
-			body.add(s);
+			body.add(s); 
 		}
 		Expect(9);
-		result = factory.finishBlock(body);
+		int length = (t.charPos + t.val.length()) - lBracePos; 
+		result = factory.finishBlock(body, lBracePos, length); 
 		return result;
 	}
 
 	SLStatementNode  Statement(boolean inLoop) {
 		SLStatementNode  result;
-		result = null;
+		result = null; 
 		switch (la.kind) {
 		case 13: {
 			result = WhileStatement();
@@ -173,13 +175,13 @@
 		}
 		case 10: {
 			Get();
-			if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); }
+			if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } 
 			Expect(11);
 			break;
 		}
 		case 12: {
 			Get();
-			if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); }
+			if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } 
 			Expect(11);
 			break;
 		}
@@ -205,11 +207,11 @@
 		SLStatementNode  result;
 		Expect(13);
 		Expect(5);
-		Token whileToken = t;
+		Token whileToken = t; 
 		SLExpressionNode condition = Expression();
 		Expect(7);
 		SLStatementNode body = Block(true);
-		result = factory.createWhile(whileToken, condition, body);
+		result = factory.createWhile(whileToken, condition, body); 
 		return result;
 	}
 
@@ -217,16 +219,16 @@
 		SLStatementNode  result;
 		Expect(14);
 		Expect(5);
-		Token ifToken = t;
+		Token ifToken = t; 
 		SLExpressionNode condition = Expression();
 		Expect(7);
 		SLStatementNode thenPart = Block(inLoop);
-		SLStatementNode elsePart = null;
+		SLStatementNode elsePart = null; 
 		if (la.kind == 15) {
 			Get();
 			elsePart = Block(inLoop);
 		}
-		result = factory.createIf(ifToken, condition, thenPart, elsePart);
+		result = factory.createIf(ifToken, condition, thenPart, elsePart); 
 		return result;
 	}
 
@@ -234,11 +236,11 @@
 		SLStatementNode  result;
 		Expect(16);
 		Token returnToken = t;
-		SLExpressionNode value = null;
+		SLExpressionNode value = null; 
 		if (StartOf(2)) {
 			value = Expression();
 		}
-		result = factory.createReturn(returnToken, value);
+		result = factory.createReturn(returnToken, value); 
 		Expect(11);
 		return result;
 	}
@@ -248,9 +250,9 @@
 		result = LogicTerm();
 		while (la.kind == 17) {
 			Get();
-			Token op = t;
+			Token op = t; 
 			SLExpressionNode right = LogicTerm();
-			result = factory.createBinary(op, result, right);
+			result = factory.createBinary(op, result, right); 
 		}
 		return result;
 	}
@@ -260,9 +262,9 @@
 		result = LogicFactor();
 		while (la.kind == 18) {
 			Get();
-			Token op = t;
+			Token op = t; 
 			SLExpressionNode right = LogicFactor();
-			result = factory.createBinary(op, result, right);
+			result = factory.createBinary(op, result, right); 
 		}
 		return result;
 	}
@@ -297,9 +299,9 @@
 				break;
 			}
 			}
-			Token op = t;
+			Token op = t; 
 			SLExpressionNode right = Arithmetic();
-			result = factory.createBinary(op, result, right);
+			result = factory.createBinary(op, result, right); 
 		}
 		return result;
 	}
@@ -313,9 +315,9 @@
 			} else {
 				Get();
 			}
-			Token op = t;
+			Token op = t; 
 			SLExpressionNode right = Term();
-			result = factory.createBinary(op, result, right);
+			result = factory.createBinary(op, result, right); 
 		}
 		return result;
 	}
@@ -329,47 +331,48 @@
 			} else {
 				Get();
 			}
-			Token op = t;
+			Token op = t; 
 			SLExpressionNode right = Factor();
-			result = factory.createBinary(op, result, right);
+			result = factory.createBinary(op, result, right); 
 		}
 		return result;
 	}
 
 	SLExpressionNode  Factor() {
 		SLExpressionNode  result;
-		result = null;
+		result = null; 
 		if (la.kind == 1) {
 			Get();
-			Token nameToken = t;
+			Token nameToken = t; 
 			if (la.kind == 5) {
 				Get();
 				List<SLExpressionNode> parameters = new ArrayList<>();
-				SLExpressionNode parameter;
+				SLExpressionNode parameter; 
 				if (StartOf(2)) {
 					parameter = Expression();
-					parameters.add(parameter);
+					parameters.add(parameter); 
 					while (la.kind == 6) {
 						Get();
 						parameter = Expression();
-						parameters.add(parameter);
+						parameters.add(parameter); 
 					}
 				}
-				result = factory.createCall(nameToken, parameters);
 				Expect(7);
+				Token finalToken = t; 
+				result = factory.createCall(nameToken, parameters, finalToken); 
 			} else if (la.kind == 29) {
 				Get();
 				SLExpressionNode value = Expression();
-				result = factory.createAssignment(nameToken, value);
+				result = factory.createAssignment(nameToken, value); 
 			} else if (StartOf(4)) {
-				result = factory.createRead(nameToken);
+				result = factory.createRead(nameToken); 
 			} else SynErr(32);
 		} else if (la.kind == 2) {
 			Get();
-			result = factory.createStringLiteral(t);
+			result = factory.createStringLiteral(t); 
 		} else if (la.kind == 3) {
 			Get();
-			result = factory.createNumericLiteral(t);
+			result = factory.createNumericLiteral(t); 
 		} else if (la.kind == 5) {
 			Get();
 			result = Expression();
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Tue Jul 15 19:21:28 2014 -0700
@@ -95,14 +95,16 @@
          * ensures that accesses to parameters are specialized the same way as local variables are
          * specialized.
          */
-        SLReadArgumentNode readArg = assignSource(nameToken, new SLReadArgumentNode(parameterCount));
+        final SourceSection src = source.createSection(nameToken.val, nameToken.charPos, nameToken.val.length());
+        SLReadArgumentNode readArg = new SLReadArgumentNode(src, parameterCount);
         methodNodes.add(createAssignment(nameToken, readArg));
         parameterCount++;
     }
 
     public void finishFunction(SLStatementNode bodyNode) {
         methodNodes.add(bodyNode);
-        SLStatementNode methodBlock = finishBlock(methodNodes);
+        // TODO (mlvdv) testing
+        SLStatementNode methodBlock = finishBlock(methodNodes, -1, -1);
         assert lexicalScope == null : "Wrong scoping of blocks in parser";
 
         SLFunctionBodyNode functionBodyNode = new SLFunctionBodyNode(methodBlock);
@@ -120,17 +122,34 @@
         lexicalScope = new LexicalScope(lexicalScope);
     }
 
-    public SLStatementNode finishBlock(List<SLStatementNode> bodyNodes) {
+    public SLStatementNode finishBlock(List<SLStatementNode> bodyNodes, int lBracePos, int length) {
         lexicalScope = lexicalScope.outer;
 
         List<SLStatementNode> flattenedNodes = new ArrayList<>(bodyNodes.size());
         flattenBlocks(bodyNodes, flattenedNodes);
+
+        if (lBracePos >= 0) {
+            final SourceSection src = source.createSection("block", lBracePos, length);
+            return new SLBlockNode(src, flattenedNodes.toArray(new SLStatementNode[flattenedNodes.size()]));
+        }
+        if (flattenedNodes.size() == 0) {
+            // TODO (mlvdv) for error reporting, should have the character position, even if the
+            // block is empty.
+            return new SLBlockNode(null, new SLStatementNode[0]);
+        }
         if (flattenedNodes.size() == 1) {
-            /* A block containing one other node is unnecessary, we can just that other node. */
+            /*
+             * A block containing one other node, not surrounded by braces is unnecessary, we can
+             * just that other node.
+             */
             return flattenedNodes.get(0);
-        } else {
-            return new SLBlockNode(flattenedNodes.toArray(new SLStatementNode[flattenedNodes.size()]));
         }
+        /*
+         * A "block" not surrounded by braces.
+         */
+        final int start = flattenedNodes.get(0).getSourceSection().getCharIndex();
+        final int end = flattenedNodes.get(flattenedNodes.size() - 1).getSourceSection().getCharEndIndex();
+        return new SLBlockNode(source.createSection("block", start, end - start), flattenedNodes.toArray(new SLStatementNode[flattenedNodes.size()]));
     }
 
     private void flattenBlocks(Iterable<? extends Node> bodyNodes, List<SLStatementNode> flattenedNodes) {
@@ -144,75 +163,90 @@
     }
 
     public SLStatementNode createBreak(Token t) {
-        return assignSource(t, new SLBreakNode());
+        return new SLBreakNode(source.createSection(t.val, t.charPos, t.val.length()));
     }
 
     public SLStatementNode createContinue(Token t) {
-        return assignSource(t, new SLContinueNode());
+        return new SLContinueNode(source.createSection(t.val, t.charPos, t.val.length()));
     }
 
     public SLStatementNode createWhile(Token t, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
-        return assignSource(t, new SLWhileNode(conditionNode, bodyNode));
+        final int start = t.charPos;
+        final int end = bodyNode.getSourceSection().getCharEndIndex();
+        return new SLWhileNode(source.createSection(t.val, start, end - start), conditionNode, bodyNode);
     }
 
     public SLStatementNode createIf(Token t, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
-        return assignSource(t, new SLIfNode(conditionNode, thenPartNode, elsePartNode));
+        final int start = t.charPos;
+        final int end = elsePartNode == null ? thenPartNode.getSourceSection().getCharEndIndex() : elsePartNode.getSourceSection().getCharEndIndex();
+        return new SLIfNode(source.createSection(t.val, start, end - start), conditionNode, thenPartNode, elsePartNode);
     }
 
     public SLStatementNode createReturn(Token t, SLExpressionNode valueNode) {
-        return assignSource(t, new SLReturnNode(valueNode));
+        final int start = t.charPos;
+        final int length = valueNode == null ? t.val.length() : valueNode.getSourceSection().getCharEndIndex() - start;
+        return new SLReturnNode(source.createSection(t.val, start, length), valueNode);
     }
 
     public SLExpressionNode createBinary(Token opToken, SLExpressionNode leftNode, SLExpressionNode rightNode) {
+        int start = leftNode.getSourceSection().getCharIndex();
+        int length = rightNode.getSourceSection().getCharEndIndex() - start;
+        final SourceSection src = source.createSection(opToken.val, start, length);
         switch (opToken.val) {
             case "+":
-                return assignSource(opToken, SLAddNodeFactory.create(leftNode, rightNode));
+                return SLAddNodeFactory.create(src, leftNode, rightNode);
             case "*":
-                return assignSource(opToken, SLMulNodeFactory.create(leftNode, rightNode));
+                return SLMulNodeFactory.create(src, leftNode, rightNode);
             case "/":
-                return assignSource(opToken, SLDivNodeFactory.create(leftNode, rightNode));
+                return SLDivNodeFactory.create(src, leftNode, rightNode);
             case "-":
-                return assignSource(opToken, SLSubNodeFactory.create(leftNode, rightNode));
+                return SLSubNodeFactory.create(src, leftNode, rightNode);
             case "<":
-                return assignSource(opToken, SLLessThanNodeFactory.create(leftNode, rightNode));
+                return SLLessThanNodeFactory.create(src, leftNode, rightNode);
             case "<=":
-                return assignSource(opToken, SLLessOrEqualNodeFactory.create(leftNode, rightNode));
+                return SLLessOrEqualNodeFactory.create(src, leftNode, rightNode);
             case ">":
-                return assignSource(opToken, SLLogicalNotNodeFactory.create(assignSource(opToken, SLLessOrEqualNodeFactory.create(leftNode, rightNode))));
+                return SLLogicalNotNodeFactory.create(src, SLLessOrEqualNodeFactory.create(null, leftNode, rightNode));
             case ">=":
-                return assignSource(opToken, SLLogicalNotNodeFactory.create(assignSource(opToken, SLLessThanNodeFactory.create(leftNode, rightNode))));
+                return SLLogicalNotNodeFactory.create(src, SLLessThanNodeFactory.create(null, leftNode, rightNode));
             case "==":
-                return assignSource(opToken, SLEqualNodeFactory.create(leftNode, rightNode));
+                return SLEqualNodeFactory.create(src, leftNode, rightNode);
             case "!=":
-                return assignSource(opToken, SLLogicalNotNodeFactory.create(assignSource(opToken, SLEqualNodeFactory.create(leftNode, rightNode))));
+                return SLLogicalNotNodeFactory.create(src, SLEqualNodeFactory.create(null, leftNode, rightNode));
             case "&&":
-                return assignSource(opToken, SLLogicalAndNodeFactory.create(leftNode, rightNode));
+                return SLLogicalAndNodeFactory.create(src, leftNode, rightNode);
             case "||":
-                return assignSource(opToken, SLLogicalOrNodeFactory.create(leftNode, rightNode));
+                return SLLogicalOrNodeFactory.create(src, leftNode, rightNode);
             default:
                 throw new RuntimeException("unexpected operation: " + opToken.val);
         }
     }
 
-    public SLExpressionNode createCall(Token nameToken, List<SLExpressionNode> parameterNodes) {
+    public SLExpressionNode createCall(Token nameToken, List<SLExpressionNode> parameterNodes, Token finalToken) {
+        final int startPos = nameToken.charPos;
+        final int endPos = finalToken.charPos + finalToken.val.length();
+        final SourceSection src = source.createSection(nameToken.val, startPos, endPos - startPos);
         SLExpressionNode functionNode = createRead(nameToken);
-        return assignSource(nameToken, SLInvokeNode.create(functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])));
+        return SLInvokeNode.create(src, functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()]));
     }
 
     public SLExpressionNode createAssignment(Token nameToken, SLExpressionNode valueNode) {
         FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(nameToken.val);
         lexicalScope.locals.put(nameToken.val, frameSlot);
-        return assignSource(nameToken, SLWriteLocalVariableNodeFactory.create(valueNode, frameSlot));
+        final int start = nameToken.charPos;
+        final int length = valueNode.getSourceSection().getCharEndIndex() - start;
+        return SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), valueNode, frameSlot);
     }
 
     public SLExpressionNode createRead(Token nameToken) {
-        FrameSlot frameSlot = lexicalScope.locals.get(nameToken.val);
+        final FrameSlot frameSlot = lexicalScope.locals.get(nameToken.val);
+        final SourceSection src = source.createSection(nameToken.val, nameToken.charPos, nameToken.val.length());
         if (frameSlot != null) {
             /* Read of a local variable. */
-            return assignSource(nameToken, SLReadLocalVariableNodeFactory.create(frameSlot));
+            return SLReadLocalVariableNodeFactory.create(src, frameSlot);
         } else {
             /* Read of a global name. In our language, the only global names are functions. */
-            return assignSource(nameToken, new SLFunctionLiteralNode(context.getFunctionRegistry().lookup(nameToken.val)));
+            return new SLFunctionLiteralNode(src, context.getFunctionRegistry().lookup(nameToken.val));
         }
     }
 
@@ -220,31 +254,21 @@
         /* Remove the trailing and ending " */
         String literal = literalToken.val;
         assert literal.length() >= 2 && literal.startsWith("\"") && literal.endsWith("\"");
+        final SourceSection src = source.createSection(literalToken.val, literalToken.charPos, literalToken.val.length());
         literal = literal.substring(1, literal.length() - 1);
 
-        return assignSource(literalToken, new SLStringLiteralNode(literal));
+        return new SLStringLiteralNode(src, literal);
     }
 
     public SLExpressionNode createNumericLiteral(Token literalToken) {
+        final SourceSection src = source.createSection(literalToken.val, literalToken.charPos, literalToken.val.length());
         try {
             /* Try if the literal is small enough to fit into a long value. */
-            return assignSource(literalToken, new SLLongLiteralNode(Long.parseLong(literalToken.val)));
+            return new SLLongLiteralNode(src, Long.parseLong(literalToken.val));
         } catch (NumberFormatException ex) {
             /* Overflow of long value, so fall back to BigInteger. */
-            return assignSource(literalToken, new SLBigIntegerLiteralNode(new BigInteger(literalToken.val)));
+            return new SLBigIntegerLiteralNode(src, new BigInteger(literalToken.val));
         }
     }
 
-    private <T extends Node> T assignSource(Token t, T node) {
-        assert functionName != null;
-        assert t != null;
-
-        int startLine = t.line;
-        int startColumn = t.col;
-        int charLength = t.val.length();
-        SourceSection sourceSection = source.createSection(functionName, startLine, startColumn, 0, charLength);
-
-        node.assignSourceSection(sourceSection);
-        return node;
-    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Tue Jul 15 19:21:28 2014 -0700
@@ -25,8 +25,11 @@
 
 package com.oracle.truffle.sl.parser;
 
-import java.io.*;
-import java.util.*;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Map;
+import java.util.HashMap;
 
 // Checkstyle: stop
 // @formatter:off
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Tue Jul 15 19:21:28 2014 -0700
@@ -84,11 +84,12 @@
 Block<out SLStatementNode result, boolean inLoop>
 =                                               (. factory.startBlock();
                                                    List<SLStatementNode> body = new ArrayList<>(); .)
-"{" 
+"{"    											(. int lBracePos = t.charPos; .)
 {
     Statement<out SLStatementNode s, inLoop>    (. body.add(s); .)
 }
-"}"                                             (. result = factory.finishBlock(body); .)
+"}"                                             (. int length = (t.charPos + t.val.length()) - lBracePos; .)
+												(. result = factory.finishBlock(body, lBracePos, length); .)
 .
 
 
@@ -210,8 +211,9 @@
                 "," 
                 Expression<out parameter>       (. parameters.add(parameter); .)
             }                                               
-        ]                                       (. result = factory.createCall(nameToken, parameters); .) 
-        ")"
+        ]
+        ")"					(. Token finalToken = t; .)
+                                               (. result = factory.createCall(nameToken, parameters, finalToken); .) 
     |
         "=" 
         Expression<out SLExpressionNode value>  (. result = factory.createAssignment(nameToken, value); .)
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Tue Jul 15 19:15:46 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Tue Jul 15 19:21:28 2014 -0700
@@ -121,7 +121,7 @@
          * from this array.
          */
         for (int i = 0; i < argumentCount; i++) {
-            argumentNodes[i] = new SLReadArgumentNode(i);
+            argumentNodes[i] = new SLReadArgumentNode(null, i);
         }
         /* Instantiate the builtin node. This node performs the actual functionality. */
         SLBuiltinNode builtinBodyNode = factory.createNode(argumentNodes, this);
--- a/mx/mx_graal.py	Tue Jul 15 19:15:46 2014 -0700
+++ b/mx/mx_graal.py	Tue Jul 15 19:21:28 2014 -0700
@@ -1281,6 +1281,12 @@
         dacapo(['-Xbatch', 'pmd'])
         tasks.append(t.stop())
 
+    # ensure -Xcomp still works
+    with VM('graal', 'product'):
+        t = Task('XCompMode:product')
+        vm(['-Xcomp', '-version'])
+        tasks.append(t.stop())
+
     if args.jacocout is not None:
         jacocoreport([args.jacocout])
 
@@ -2049,7 +2055,7 @@
             tmp = tempfile.mkdtemp(prefix='findbugs-download-tmp', dir=_graal_home)
             try:
                 findbugsDist = join(tmp, 'findbugs.zip')
-                mx.download(findbugsDist, ['http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0-dev-20131204-e3cbbd5.zip'])
+                mx.download(findbugsDist, ['http://lafo.ssw.uni-linz.ac.at/graal-external-deps/findbugs-3.0.0.zip', 'http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0.zip'])
                 with zipfile.ZipFile(findbugsDist) as zf:
                     candidates = [e for e in zf.namelist() if e.endswith('/lib/findbugs.jar')]
                     assert len(candidates) == 1, candidates
--- a/mx/projects	Tue Jul 15 19:15:46 2014 -0700
+++ b/mx/projects	Tue Jul 15 19:21:28 2014 -0700
@@ -23,9 +23,9 @@
 library@CHECKSTYLE@path=lib/checkstyle-5.5-all.jar
 library@CHECKSTYLE@urls=jar:http://sourceforge.net/projects/checkstyle/files/checkstyle/5.5/checkstyle-5.5-bin.zip/download!/checkstyle-5.5/checkstyle-5.5-all.jar
 
-library@FINDBUGS@path=lib/findbugs-3.0.0-rc1.jar
-library@FINDBUGS@urls=jar:http://lafo.ssw.uni-linz.ac.at/graal-external-deps/findbugs-3.0.0-rc1.zip!/findbugs-3.0.0-rc1/lib/findbugs.jar,jar:http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0-rc1.zip/download!/findbugs-3.0.0-rc1/lib/findbugs.jar
-library@FINDBUGS@sha1=3a0a592608b41b57a77721b933b7bb78fcf64015
+library@FINDBUGS@path=lib/findbugs-3.0.0.jar
+library@FINDBUGS@urls=jar:http://lafo.ssw.uni-linz.ac.at/graal-external-deps/findbugs-3.0.0.zip!/findbugs-3.0.0/lib/findbugs.jar,jar:http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0.zip/download!/findbugs-3.0.0/lib/findbugs.jar
+library@FINDBUGS@sha1=e9a938f0cb34e2ab5853f9ecb1989f6f590ee385
 
 library@DACAPO@path=lib/dacapo-9.12-bach.jar
 library@DACAPO@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/dacapo-9.12-bach.jar,http://softlayer.dl.sourceforge.net/project/dacapobench/9.12-bach/dacapo-9.12-bach.jar
@@ -135,14 +135,6 @@
 project@com.oracle.graal.api.meta.test@javaCompliance=1.8
 project@com.oracle.graal.api.meta.test@workingSets=API,Graal,Test
 
-# graal.api.meta.jdk8.test
-project@com.oracle.graal.api.meta.jdk8.test@subDir=graal
-project@com.oracle.graal.api.meta.jdk8.test@sourceDirs=src
-project@com.oracle.graal.api.meta.jdk8.test@dependencies=com.oracle.graal.api.meta.test
-project@com.oracle.graal.api.meta.jdk8.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.api.meta.jdk8.test@javaCompliance=1.8
-project@com.oracle.graal.api.meta.jdk8.test@workingSets=API,Graal,Test
-
 # graal.api.code
 project@com.oracle.graal.api.code@subDir=graal
 project@com.oracle.graal.api.code@sourceDirs=src
--- a/mxtool/mx.py	Tue Jul 15 19:15:46 2014 -0700
+++ b/mxtool/mx.py	Tue Jul 15 19:21:28 2014 -0700
@@ -2043,7 +2043,7 @@
                 rootJdtProperties = join(self.proj.suite.mxDir, 'eclipse-settings', 'org.eclipse.jdt.core.prefs')
                 if not exists(jdtProperties) or os.path.getmtime(jdtProperties) < os.path.getmtime(rootJdtProperties):
                     # Try to fix a missing properties file by running eclipseinit
-                    eclipseinit([], buildProcessorJars=False)
+                    _eclipseinit_project(self.proj)
                 if not exists(jdtProperties):
                     log('JDT properties file {0} not found'.format(jdtProperties))
                 else:
@@ -3174,6 +3174,229 @@
                     return False
     return True
 
+def _eclipseinit_project(p, files=None, libFiles=None):
+    assert java(p.javaCompliance)
+
+    if not exists(p.dir):
+        os.makedirs(p.dir)
+
+    out = XMLDoc()
+    out.open('classpath')
+
+    for src in p.srcDirs:
+        srcDir = join(p.dir, src)
+        if not exists(srcDir):
+            os.mkdir(srcDir)
+        out.element('classpathentry', {'kind' : 'src', 'path' : src})
+
+    if len(p.annotation_processors()) > 0:
+        genDir = p.source_gen_dir()
+        if not exists(genDir):
+            os.mkdir(genDir)
+        out.element('classpathentry', {'kind' : 'src', 'path' : 'src_gen'})
+        if files:
+            files.append(genDir)
+
+    # Every Java program depends on a JRE
+    out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-' + str(p.javaCompliance)})
+
+    if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
+        out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.pde.core.requiredPlugins'})
+
+    containerDeps = set()
+    libraryDeps = set()
+    projectDeps = set()
+
+    for dep in p.all_deps([], True):
+        if dep == p:
+            continue
+        if dep.isLibrary():
+            if hasattr(dep, 'eclipse.container'):
+                container = getattr(dep, 'eclipse.container')
+                containerDeps.add(container)
+                libraryDeps -= set(dep.all_deps([], True))
+            else:
+                libraryDeps.add(dep)
+        elif dep.isProject():
+            projectDeps.add(dep)
+
+    for dep in containerDeps:
+        out.element('classpathentry', {'exported' : 'true', 'kind' : 'con', 'path' : dep})
+
+    for dep in libraryDeps:
+        path = dep.path
+        dep.get_path(resolve=True)
+
+        # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
+        # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
+        # safest to simply use absolute paths.
+        path = _make_absolute(path, p.suite.dir)
+
+        attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path}
+
+        sourcePath = dep.get_source_path(resolve=True)
+        if sourcePath is not None:
+            attributes['sourcepath'] = sourcePath
+        out.element('classpathentry', attributes)
+        if libFiles:
+            libFiles.append(path)
+
+    for dep in projectDeps:
+        out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name})
+
+    out.element('classpathentry', {'kind' : 'output', 'path' : getattr(p, 'eclipse.output', 'bin')})
+    out.close('classpath')
+    classpathFile = join(p.dir, '.classpath')
+    update_file(classpathFile, out.xml(indent='\t', newl='\n'))
+    if files:
+        files.append(classpathFile)
+
+    csConfig = join(project(p.checkstyleProj).dir, '.checkstyle_checks.xml')
+    if exists(csConfig):
+        out = XMLDoc()
+
+        dotCheckstyle = join(p.dir, ".checkstyle")
+        checkstyleConfigPath = '/' + p.checkstyleProj + '/.checkstyle_checks.xml'
+        out.open('fileset-config', {'file-format-version' : '1.2.0', 'simple-config' : 'true'})
+        out.open('local-check-config', {'name' : 'Checks', 'location' : checkstyleConfigPath, 'type' : 'project', 'description' : ''})
+        out.element('additional-data', {'name' : 'protect-config-file', 'value' : 'false'})
+        out.close('local-check-config')
+        out.open('fileset', {'name' : 'all', 'enabled' : 'true', 'check-config-name' : 'Checks', 'local' : 'true'})
+        out.element('file-match-pattern', {'match-pattern' : '.', 'include-pattern' : 'true'})
+        out.close('fileset')
+        out.open('filter', {'name' : 'all', 'enabled' : 'true', 'check-config-name' : 'Checks', 'local' : 'true'})
+        out.element('filter-data', {'value' : 'java'})
+        out.close('filter')
+
+        exclude = join(p.dir, '.checkstyle.exclude')
+        if exists(exclude):
+            out.open('filter', {'name' : 'FilesFromPackage', 'enabled' : 'true'})
+            with open(exclude) as f:
+                for line in f:
+                    if not line.startswith('#'):
+                        line = line.strip()
+                        exclDir = join(p.dir, line)
+                        assert isdir(exclDir), 'excluded source directory listed in ' + exclude + ' does not exist or is not a directory: ' + exclDir
+                    out.element('filter-data', {'value' : line})
+            out.close('filter')
+
+        out.close('fileset-config')
+        update_file(dotCheckstyle, out.xml(indent='  ', newl='\n'))
+        if files:
+            files.append(dotCheckstyle)
+    else:
+        # clean up existing .checkstyle file
+        dotCheckstyle = join(p.dir, ".checkstyle")
+        if exists(dotCheckstyle):
+            os.unlink(dotCheckstyle)
+
+    out = XMLDoc()
+    out.open('projectDescription')
+    out.element('name', data=p.name)
+    out.element('comment', data='')
+    out.element('projects', data='')
+    out.open('buildSpec')
+    out.open('buildCommand')
+    out.element('name', data='org.eclipse.jdt.core.javabuilder')
+    out.element('arguments', data='')
+    out.close('buildCommand')
+    if exists(csConfig):
+        out.open('buildCommand')
+        out.element('name', data='net.sf.eclipsecs.core.CheckstyleBuilder')
+        out.element('arguments', data='')
+        out.close('buildCommand')
+    if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
+        for buildCommand in ['org.eclipse.pde.ManifestBuilder', 'org.eclipse.pde.SchemaBuilder']:
+            out.open('buildCommand')
+            out.element('name', data=buildCommand)
+            out.element('arguments', data='')
+            out.close('buildCommand')
+
+    # The path should always be p.name/dir. independent of where the workspace actually is.
+    # So we use the parent folder of the project, whatever that is, to generate such a relative path.
+    logicalWorkspaceRoot = os.path.dirname(p.dir)
+    binFolder = os.path.relpath(p.output_dir(), logicalWorkspaceRoot)
+
+    if _isAnnotationProcessorDependency(p):
+        refreshFile = os.path.relpath(join(p.dir, p.name + '.jar'), logicalWorkspaceRoot)
+        _genEclipseBuilder(out, p, 'Jar', 'archive ' + p.name, refresh=True, refreshFile=refreshFile, relevantResources=[binFolder], async=True, xmlIndent='', xmlStandalone='no')
+
+    out.close('buildSpec')
+    out.open('natures')
+    out.element('nature', data='org.eclipse.jdt.core.javanature')
+    if exists(csConfig):
+        out.element('nature', data='net.sf.eclipsecs.core.CheckstyleNature')
+    if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
+        out.element('nature', data='org.eclipse.pde.PluginNature')
+    out.close('natures')
+    out.close('projectDescription')
+    projectFile = join(p.dir, '.project')
+    update_file(projectFile, out.xml(indent='\t', newl='\n'))
+    if files:
+        files.append(projectFile)
+
+    settingsDir = join(p.dir, ".settings")
+    if not exists(settingsDir):
+        os.mkdir(settingsDir)
+
+    # collect the defaults from mxtool
+    defaultEclipseSettingsDir = join(dirname(__file__), 'eclipse-settings')
+    esdict = {}
+    if exists(defaultEclipseSettingsDir):
+        for name in os.listdir(defaultEclipseSettingsDir):
+            if isfile(join(defaultEclipseSettingsDir, name)):
+                esdict[name] = os.path.abspath(join(defaultEclipseSettingsDir, name))
+
+    # check for suite overrides
+    eclipseSettingsDir = join(p.suite.mxDir, 'eclipse-settings')
+    if exists(eclipseSettingsDir):
+        for name in os.listdir(eclipseSettingsDir):
+            if isfile(join(eclipseSettingsDir, name)):
+                esdict[name] = os.path.abspath(join(eclipseSettingsDir, name))
+
+    # check for project overrides
+    projectSettingsDir = join(p.dir, 'eclipse-settings')
+    if exists(projectSettingsDir):
+        for name in os.listdir(projectSettingsDir):
+            if isfile(join(projectSettingsDir, name)):
+                esdict[name] = os.path.abspath(join(projectSettingsDir, name))
+
+    # copy a possibly modified file to the project's .settings directory
+    for name, path in esdict.iteritems():
+        # ignore this file altogether if this project has no annotation processors
+        if name == "org.eclipse.jdt.apt.core.prefs" and not len(p.annotation_processors()) > 0:
+            continue
+
+        with open(path) as f:
+            content = f.read()
+        content = content.replace('${javaCompliance}', str(p.javaCompliance))
+        if len(p.annotation_processors()) > 0:
+            content = content.replace('org.eclipse.jdt.core.compiler.processAnnotations=disabled', 'org.eclipse.jdt.core.compiler.processAnnotations=enabled')
+        update_file(join(settingsDir, name), content)
+        if files:
+            files.append(join(settingsDir, name))
+
+    if len(p.annotation_processors()) > 0:
+        out = XMLDoc()
+        out.open('factorypath')
+        out.element('factorypathentry', {'kind' : 'PLUGIN', 'id' : 'org.eclipse.jst.ws.annotations.core', 'enabled' : 'true', 'runInBatchMode' : 'false'})
+        for ap in p.annotation_processors():
+            for dep in dependency(ap).all_deps([], True):
+                if dep.isLibrary():
+                    # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
+                    # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
+                    # safest to simply use absolute paths.
+                    path = _make_absolute(dep.get_path(resolve=True), p.suite.dir)
+                    out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'})
+                    if files:
+                        files.append(path)
+                elif dep.isProject():
+                    out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'})
+        out.close('factorypath')
+        update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n'))
+        if files:
+            files.append(join(p.dir, '.factorypath'))
+
 def _eclipseinit_suite(args, suite, buildProcessorJars=True, refreshOnly=False):
     configZip = TimeStampFile(join(suite.mxDir, 'eclipse-config.zip'))
     configLibsZip = join(suite.mxDir, 'eclipse-config-libs.zip')
@@ -3184,6 +3407,8 @@
         logv('[Eclipse configurations are up to date - skipping]')
         return
 
+
+
     files = []
     libFiles = []
     if buildProcessorJars:
@@ -3198,220 +3423,7 @@
     for p in suite.projects:
         if p.native:
             continue
-
-        assert java(p.javaCompliance)
-
-        if not exists(p.dir):
-            os.makedirs(p.dir)
-
-        out = XMLDoc()
-        out.open('classpath')
-
-        for src in p.srcDirs:
-            srcDir = join(p.dir, src)
-            if not exists(srcDir):
-                os.mkdir(srcDir)
-            out.element('classpathentry', {'kind' : 'src', 'path' : src})
-
-        if len(p.annotation_processors()) > 0:
-            genDir = p.source_gen_dir()
-            if not exists(genDir):
-                os.mkdir(genDir)
-            out.element('classpathentry', {'kind' : 'src', 'path' : 'src_gen'})
-            files.append(genDir)
-
-        # Every Java program depends on a JRE
-        out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-' + str(p.javaCompliance)})
-
-        if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
-            out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.pde.core.requiredPlugins'})
-
-        containerDeps = set()
-        libraryDeps = set()
-        projectDeps = set()
-
-        for dep in p.all_deps([], True):
-            if dep == p:
-                continue
-            if dep.isLibrary():
-                if hasattr(dep, 'eclipse.container'):
-                    container = getattr(dep, 'eclipse.container')
-                    containerDeps.add(container)
-                    libraryDeps -= set(dep.all_deps([], True))
-                else:
-                    libraryDeps.add(dep)
-            elif dep.isProject():
-                projectDeps.add(dep)
-
-        for dep in containerDeps:
-            out.element('classpathentry', {'exported' : 'true', 'kind' : 'con', 'path' : dep})
-
-        for dep in libraryDeps:
-            path = dep.path
-            dep.get_path(resolve=True)
-
-            # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
-            # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
-            # safest to simply use absolute paths.
-            path = _make_absolute(path, p.suite.dir)
-
-            attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path}
-
-            sourcePath = dep.get_source_path(resolve=True)
-            if sourcePath is not None:
-                attributes['sourcepath'] = sourcePath
-            out.element('classpathentry', attributes)
-            libFiles.append(path)
-
-        for dep in projectDeps:
-            out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name})
-
-        out.element('classpathentry', {'kind' : 'output', 'path' : getattr(p, 'eclipse.output', 'bin')})
-        out.close('classpath')
-        classpathFile = join(p.dir, '.classpath')
-        update_file(classpathFile, out.xml(indent='\t', newl='\n'))
-        files.append(classpathFile)
-
-        csConfig = join(project(p.checkstyleProj).dir, '.checkstyle_checks.xml')
-        if exists(csConfig):
-            out = XMLDoc()
-
-            dotCheckstyle = join(p.dir, ".checkstyle")
-            checkstyleConfigPath = '/' + p.checkstyleProj + '/.checkstyle_checks.xml'
-            out.open('fileset-config', {'file-format-version' : '1.2.0', 'simple-config' : 'true'})
-            out.open('local-check-config', {'name' : 'Checks', 'location' : checkstyleConfigPath, 'type' : 'project', 'description' : ''})
-            out.element('additional-data', {'name' : 'protect-config-file', 'value' : 'false'})
-            out.close('local-check-config')
-            out.open('fileset', {'name' : 'all', 'enabled' : 'true', 'check-config-name' : 'Checks', 'local' : 'true'})
-            out.element('file-match-pattern', {'match-pattern' : '.', 'include-pattern' : 'true'})
-            out.close('fileset')
-            out.open('filter', {'name' : 'all', 'enabled' : 'true', 'check-config-name' : 'Checks', 'local' : 'true'})
-            out.element('filter-data', {'value' : 'java'})
-            out.close('filter')
-
-            exclude = join(p.dir, '.checkstyle.exclude')
-            if exists(exclude):
-                out.open('filter', {'name' : 'FilesFromPackage', 'enabled' : 'true'})
-                with open(exclude) as f:
-                    for line in f:
-                        if not line.startswith('#'):
-                            line = line.strip()
-                            exclDir = join(p.dir, line)
-                            assert isdir(exclDir), 'excluded source directory listed in ' + exclude + ' does not exist or is not a directory: ' + exclDir
-                        out.element('filter-data', {'value' : line})
-                out.close('filter')
-
-            out.close('fileset-config')
-            update_file(dotCheckstyle, out.xml(indent='  ', newl='\n'))
-            files.append(dotCheckstyle)
-        else:
-            # clean up existing .checkstyle file
-            dotCheckstyle = join(p.dir, ".checkstyle")
-            if exists(dotCheckstyle):
-                os.unlink(dotCheckstyle)
-
-        out = XMLDoc()
-        out.open('projectDescription')
-        out.element('name', data=p.name)
-        out.element('comment', data='')
-        out.element('projects', data='')
-        out.open('buildSpec')
-        out.open('buildCommand')
-        out.element('name', data='org.eclipse.jdt.core.javabuilder')
-        out.element('arguments', data='')
-        out.close('buildCommand')
-        if exists(csConfig):
-            out.open('buildCommand')
-            out.element('name', data='net.sf.eclipsecs.core.CheckstyleBuilder')
-            out.element('arguments', data='')
-            out.close('buildCommand')
-        if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
-            for buildCommand in ['org.eclipse.pde.ManifestBuilder', 'org.eclipse.pde.SchemaBuilder']:
-                out.open('buildCommand')
-                out.element('name', data=buildCommand)
-                out.element('arguments', data='')
-                out.close('buildCommand')
-
-        # The path should always be p.name/dir. independent of where the workspace actually is.
-        # So we use the parent folder of the project, whatever that is, to generate such a relative path.
-        logicalWorkspaceRoot = os.path.dirname(p.dir)
-        binFolder = os.path.relpath(p.output_dir(), logicalWorkspaceRoot)
-
-        if _isAnnotationProcessorDependency(p):
-            refreshFile = os.path.relpath(join(p.dir, p.name + '.jar'), logicalWorkspaceRoot)
-            _genEclipseBuilder(out, p, 'Jar', 'archive ' + p.name, refresh=True, refreshFile=refreshFile, relevantResources=[binFolder], async=True, xmlIndent='', xmlStandalone='no')
-
-        out.close('buildSpec')
-        out.open('natures')
-        out.element('nature', data='org.eclipse.jdt.core.javanature')
-        if exists(csConfig):
-            out.element('nature', data='net.sf.eclipsecs.core.CheckstyleNature')
-        if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
-            out.element('nature', data='org.eclipse.pde.PluginNature')
-        out.close('natures')
-        out.close('projectDescription')
-        projectFile = join(p.dir, '.project')
-        update_file(projectFile, out.xml(indent='\t', newl='\n'))
-        files.append(projectFile)
-
-        settingsDir = join(p.dir, ".settings")
-        if not exists(settingsDir):
-            os.mkdir(settingsDir)
-
-        # collect the defaults from mxtool
-        defaultEclipseSettingsDir = join(dirname(__file__), 'eclipse-settings')
-        esdict = {}
-        if exists(defaultEclipseSettingsDir):
-            for name in os.listdir(defaultEclipseSettingsDir):
-                if isfile(join(defaultEclipseSettingsDir, name)):
-                    esdict[name] = os.path.abspath(join(defaultEclipseSettingsDir, name))
-
-        # check for suite overrides
-        eclipseSettingsDir = join(p.suite.mxDir, 'eclipse-settings')
-        if exists(eclipseSettingsDir):
-            for name in os.listdir(eclipseSettingsDir):
-                if isfile(join(eclipseSettingsDir, name)):
-                    esdict[name] = os.path.abspath(join(eclipseSettingsDir, name))
-
-        # check for project overrides
-        projectSettingsDir = join(p.dir, 'eclipse-settings')
-        if exists(projectSettingsDir):
-            for name in os.listdir(projectSettingsDir):
-                if isfile(join(projectSettingsDir, name)):
-                    esdict[name] = os.path.abspath(join(projectSettingsDir, name))
-
-        # copy a possibly modified file to the project's .settings directory
-        for name, path in esdict.iteritems():
-            # ignore this file altogether if this project has no annotation processors
-            if name == "org.eclipse.jdt.apt.core.prefs" and not len(p.annotation_processors()) > 0:
-                continue
-
-            with open(path) as f:
-                content = f.read()
-            content = content.replace('${javaCompliance}', str(p.javaCompliance))
-            if len(p.annotation_processors()) > 0:
-                content = content.replace('org.eclipse.jdt.core.compiler.processAnnotations=disabled', 'org.eclipse.jdt.core.compiler.processAnnotations=enabled')
-            update_file(join(settingsDir, name), content)
-            files.append(join(settingsDir, name))
-
-        if len(p.annotation_processors()) > 0:
-            out = XMLDoc()
-            out.open('factorypath')
-            out.element('factorypathentry', {'kind' : 'PLUGIN', 'id' : 'org.eclipse.jst.ws.annotations.core', 'enabled' : 'true', 'runInBatchMode' : 'false'})
-            for ap in p.annotation_processors():
-                for dep in dependency(ap).all_deps([], True):
-                    if dep.isLibrary():
-                        # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
-                        # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
-                        # safest to simply use absolute paths.
-                        path = _make_absolute(dep.get_path(resolve=True), p.suite.dir)
-                        out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'})
-                        files.append(path)
-                    elif dep.isProject():
-                        out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'})
-            out.close('factorypath')
-            update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n'))
-            files.append(join(p.dir, '.factorypath'))
+        _eclipseinit_project(p)
 
     _, launchFile = make_eclipse_attach(suite, 'localhost', '8000', deps=sorted_deps(projectNames=None, includeLibs=True))
     files.append(launchFile)
@@ -3422,7 +3434,6 @@
     # Create an Eclipse project for each distribution that will create/update the archive
     # for the distribution whenever any project of the distribution is updated.
     for dist in suite.dists:
-        name = dist.name
         if hasattr(dist, 'subDir'):
             projectDir = join(suite.dir, dist.subDir, dist.name + '.dist')
         else:
--- a/src/share/vm/compiler/compileBroker.cpp	Tue Jul 15 19:15:46 2014 -0700
+++ b/src/share/vm/compiler/compileBroker.cpp	Tue Jul 15 19:21:28 2014 -0700
@@ -51,6 +51,9 @@
 #endif
 #ifdef GRAAL
 #include "graal/graalCompiler.hpp"
+#ifdef COMPILERGRAAL
+#include "runtime/vframe.hpp"
+#endif
 #endif
 #ifdef COMPILER2
 #include "opto/c2compiler.hpp"
@@ -1187,10 +1190,22 @@
     blocking = is_compile_blocking(method, osr_bci);
 
 #ifdef COMPILERGRAAL
-    // Don't allow blocking compiles for requests triggered by Graal.
-    if (blocking && thread->is_Compiler_thread()) {
-      blocking = false;
+    if (blocking) {
+      // Don't allow blocking compiles for requests triggered by Graal.
+      if (thread->is_Compiler_thread()) {
+        blocking = false;
+      }
+
+      // Don't allow blocking compiles if inside a class initializer
+      vframeStream vfst((JavaThread*) thread);
+      for (; !vfst.at_end(); vfst.next()) {
+        if (vfst.method()->is_static_initializer()) {
+          blocking = false;
+          break;
+        }
+      }
     }
+    // Don't allow blocking compiles
 #endif
 
     // We will enter the compilation in the queue.
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Tue Jul 15 19:15:46 2014 -0700
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Tue Jul 15 19:21:28 2014 -0700
@@ -234,11 +234,13 @@
   Klass* resolved_klass = NULL;
   Handle class_loader;
   Handle protection_domain;
-  if (JNIHandles::resolve(accessing_class) != NULL) {
-    Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class));
-    class_loader = accessing_klass->class_loader();
-    protection_domain = accessing_klass->protection_domain();
+  if (JNIHandles::resolve(accessing_class) == NULL) {
+    THROW_(vmSymbols::java_lang_NullPointerException(), 0L);
   }
+  Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class));
+  class_loader = accessing_klass->class_loader();
+  protection_domain = accessing_klass->protection_domain();
+
 
   if (resolve) {
     resolved_klass = SystemDictionary::resolve_or_fail(class_name, class_loader, protection_domain, true, THREAD);