changeset 16471:352de9bd8fd5

Merge
author Andreas Woess <andreas.woess@jku.at>
date Thu, 10 Jul 2014 19:36:27 +0200
parents cec5a97ba1e4 (diff) efbf9195dfcb (current diff)
children 83dce5b6cb41
files
diffstat 81 files changed, 1314 insertions(+), 1341 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Local.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Local.java	Thu Jul 10 19:36:27 2014 +0200
@@ -32,5 +32,5 @@
 
     String getName();
 
-    ResolvedJavaType getType();
+    JavaType getType();
 }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Jul 10 19:36:27 2014 +0200
@@ -609,7 +609,7 @@
                 append(new BinaryRegReg(IDIV, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new BinaryRegReg(LDIV, result, a, loadNonConst(b)));
+                append(new BinaryRegReg(LDIV, result, a, loadNonConst(b), state));
                 break;
             case Float:
                 append(new Op2Stack(FDIV, result, a, loadNonConst(b)));
@@ -825,13 +825,21 @@
                 conversionInstruction = F2I;
                 break;
             case I2D:
-                return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Double), I2D, input);
+            // Implemented in two steps, as this consists of sign extension and then move the
+            // bits over to the double register and then convert to double, in fact this does
+            // not generate any overhead in generated code
+            {
+                AllocatableValue tmp = emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Long), I2L, input);
+                return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Double), L2D, tmp);
+            }
             case I2F:
                 return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Float), I2F, input);
             case L2D:
                 return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Double), L2D, input);
-            case L2F:
-                return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Float), L2F, input);
+            case L2F: {
+                AllocatableValue tmp = emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Double), L2D, input);
+                return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Float), D2F, tmp);
+            }
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/MemoryScheduleTest.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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.debug/src/com/oracle/graal/debug/Debug.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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.loader/src/com/oracle/graal/hotspot/loader/Factory.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java	Thu Jul 10 19:36:27 2014 +0200
@@ -32,8 +32,11 @@
 
     /**
      * Creates a new class loader for loading classes in {@code graal.jar}.
+     *
+     * Called from the VM.
      */
-    public static ClassLoader newClassLoader() throws MalformedURLException {
+    @SuppressWarnings("unused")
+    private static ClassLoader newClassLoader() throws MalformedURLException {
         URL[] urls = {getGraalJarUrl()};
         return URLClassLoader.newInstance(urls);
     }
--- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Thu Jul 10 19:36:27 2014 +0200
@@ -166,7 +166,7 @@
                 out.printf("      if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len);
                 out.println("        if (value[0] == '+') {");
                 out.println("          if (check_only) {");
-                out.println("            TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", THREAD);");
+                out.println("            TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", CHECK_(true));");
                 out.println("            hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, CHECK_(true));");
                 out.println("          }");
                 out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), '?', Handle(), 0L);");
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/debug/LocalImpl.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/LocalImpl.java	Thu Jul 10 19:36:27 2014 +0200
@@ -33,19 +33,14 @@
     private final int startBci;
     private final int endBci;
     private final int slot;
-    private final ResolvedJavaType resolvedType;
+    private final JavaType type;
 
     public LocalImpl(String name, String type, HotSpotResolvedObjectType holder, int startBci, int endBci, int slot) {
         this.name = name;
         this.startBci = startBci;
         this.endBci = endBci;
         this.slot = slot;
-        JavaType t = runtime().lookupType(type, holder, true);
-        if (t instanceof ResolvedJavaType) {
-            this.resolvedType = (ResolvedJavaType) runtime().lookupType(type, holder, false);
-        } else {
-            throw new AssertionError(t.getClass() + " is not a ResolvedJavaType");
-        }
+        this.type = runtime().lookupType(type, holder, false);
     }
 
     @Override
@@ -64,8 +59,8 @@
     }
 
     @Override
-    public ResolvedJavaType getType() {
-        return resolvedType;
+    public JavaType getType() {
+        return type;
     }
 
     @Override
@@ -79,7 +74,7 @@
             return false;
         }
         LocalImpl that = (LocalImpl) obj;
-        return this.name.equals(that.name) && this.startBci == that.startBci && this.endBci == that.endBci && this.slot == that.slot && this.resolvedType.equals(that.resolvedType);
+        return this.name.equals(that.name) && this.startBci == that.startBci && this.endBci == that.endBci && this.slot == that.slot && this.type.equals(that.type);
     }
 
     @Override
@@ -89,6 +84,6 @@
 
     @Override
     public String toString() {
-        return "LocalImpl<name=" + name + ", resolvedType=" + resolvedType + ", 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/nodes/DeoptimizationFetchUnrollInfoCallNode.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/UncommonTrapCallNode.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/phases/WriteBarrierAdditionPhase.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AssertionSnippets.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/stubs/DeoptimizationStub.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/Stub.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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.jtt/src/com/oracle/graal/jtt/bytecode/BC_l2f.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_l2f.java	Thu Jul 10 19:36:27 2014 +0200
@@ -49,4 +49,14 @@
         runTest("test", -74652389L);
     }
 
+    @Test
+    public void run3() throws Throwable {
+        runTest("test", Long.MAX_VALUE);
+    }
+
+    @Test
+    public void run4() throws Throwable {
+        runTest("test", Long.MIN_VALUE);
+    }
+
 }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/IfNode.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/InvokeWithExceptionNode.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ /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/ProxyNode.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/extended/AbstractWriteNode.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/MonitorExitNode.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/type/StampTool.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/src/com/oracle/graal/phases/BasePhase.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Thu Jul 10 19:36:27 2014 +0200
@@ -1050,7 +1050,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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/SnippetTemplate.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Thu Jul 10 19:36:27 2014 +0200
@@ -669,7 +669,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 +694,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) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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/PartialEvaluator.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Jul 10 19:36:27 2014 +0200
@@ -202,7 +202,7 @@
                         }
 
                         StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod());
-                        if (inlineGraph == null && !methodCallTargetNode.targetMethod().isNative() && methodCallTargetNode.targetMethod().canBeInlined()) {
+                        if (inlineGraph == null && canBeInlined(methodCallTargetNode)) {
                             inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext, false);
                         }
 
@@ -242,6 +242,10 @@
         }
     }
 
+    private static boolean canBeInlined(MethodCallTargetNode methodCallTargetNode) {
+        return !methodCallTargetNode.targetMethod().isNative() && methodCallTargetNode.targetMethod().getAnnotation(TruffleCallBoundary.class) == null;
+    }
+
     private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList<ValueNode> arguments, final Assumptions assumptions, final PhaseContext phaseContext,
                     boolean ignoreSlowPath) {
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Thu Jul 10 19:36:27 2014 +0200
@@ -67,7 +67,7 @@
 
     private final ResolvedJavaType stringBuilderClass;
     private final ResolvedJavaType runtimeExceptionClass;
-    private final ResolvedJavaType assertionErrorClass;
+    private final ResolvedJavaType errorClass;
     private final ResolvedJavaType controlFlowExceptionClass;
 
     private final ResolvedJavaMethod callBoundaryMethod;
@@ -81,7 +81,7 @@
 
         this.stringBuilderClass = providers.getMetaAccess().lookupJavaType(StringBuilder.class);
         this.runtimeExceptionClass = providers.getMetaAccess().lookupJavaType(RuntimeException.class);
-        this.assertionErrorClass = providers.getMetaAccess().lookupJavaType(AssertionError.class);
+        this.errorClass = providers.getMetaAccess().lookupJavaType(Error.class);
         this.controlFlowExceptionClass = providers.getMetaAccess().lookupJavaType(ControlFlowException.class);
 
         try {
@@ -192,7 +192,7 @@
                                 if (macroSubstitution != null) {
                                     InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), macroSubstitution);
                                 } else {
-                                    tryCutOffRuntimeExceptions(methodCallTargetNode);
+                                    tryCutOffRuntimeExceptionsAndErrors(methodCallTargetNode);
                                 }
                             }
                         }
@@ -257,14 +257,14 @@
         InliningUtil.inline(invoke, inlineGraph, true, null);
     }
 
-    private boolean tryCutOffRuntimeExceptions(MethodCallTargetNode methodCallTargetNode) {
+    private boolean tryCutOffRuntimeExceptionsAndErrors(MethodCallTargetNode methodCallTargetNode) {
         if (methodCallTargetNode.targetMethod().isConstructor()) {
             ResolvedJavaType declaringClass = methodCallTargetNode.targetMethod().getDeclaringClass();
             ResolvedJavaType exceptionType = Objects.requireNonNull(StampTool.typeOrNull(methodCallTargetNode.receiver().stamp()));
 
-            boolean removeAllocation = runtimeExceptionClass.isAssignableFrom(declaringClass) || assertionErrorClass.isAssignableFrom(declaringClass);
-            boolean isCFGException = controlFlowExceptionClass.isAssignableFrom(exceptionType);
-            if (removeAllocation && !isCFGException) {
+            boolean removeAllocation = runtimeExceptionClass.isAssignableFrom(declaringClass) || errorClass.isAssignableFrom(declaringClass);
+            boolean isControlFlowException = controlFlowExceptionClass.isAssignableFrom(exceptionType);
+            if (removeAllocation && !isControlFlowException) {
                 DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode));
                 FixedNode invokeNode = methodCallTargetNode.invoke().asNode();
                 invokeNode.replaceAtPredecessor(deoptNode);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -24,6 +24,8 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.replacements.nodes.*;
 
 public class NeverPartOfCompilationNode extends MacroNode implements IterableNodeType {
@@ -40,6 +42,11 @@
     }
 
     public final String getMessage() {
-        return message;
+        return message + " " + arguments.toString();
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        throw GraphUtil.approxSourceException(this, new VerificationError(getMessage()));
     }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Jul 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Jul 10 19:36:27 2014 +0200
@@ -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;
@@ -891,4 +851,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/mx/mx_graal.py	Tue Jul 08 20:19:34 2014 +0200
+++ b/mx/mx_graal.py	Thu Jul 10 19:36:27 2014 +0200
@@ -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])
 
--- a/mxtool/mx.py	Tue Jul 08 20:19:34 2014 +0200
+++ b/mxtool/mx.py	Thu Jul 10 19:36:27 2014 +0200
@@ -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 08 20:19:34 2014 +0200
+++ b/src/share/vm/compiler/compileBroker.cpp	Thu Jul 10 19:36:27 2014 +0200
@@ -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/graalCompiler.cpp	Tue Jul 08 20:19:34 2014 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Thu Jul 10 19:36:27 2014 +0200
@@ -133,8 +133,7 @@
   args.push_int(entry_bci);
   args.push_long((jlong) (address) task);
   args.push_int(task->compile_id());
-  JavaCalls::call_static(&result, SystemDictionary::CompilationTask_klass(), vmSymbols::compileMetaspaceMethod_name(), vmSymbols::compileMetaspaceMethod_signature(), &args, THREAD);
-  GUARANTEE_NO_PENDING_EXCEPTION("Error while calling compile_method");
+  JavaCalls::call_static(&result, SystemDictionary::CompilationTask_klass(), vmSymbols::compileMetaspaceMethod_name(), vmSymbols::compileMetaspaceMethod_signature(), &args, CHECK_ABORT);
 
   _methodsCompiled++;
 }
@@ -159,13 +158,12 @@
   CompileTheWorld = false;
 
   JavaThread* THREAD = JavaThread::current();
-  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", THREAD);
+  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", CHECK_ABORT);
   KlassHandle klass = GraalRuntime::load_required_class(name);
-  TempNewSymbol compileTheWorld = SymbolTable::new_symbol("compileTheWorld", THREAD);
+  TempNewSymbol compileTheWorld = SymbolTable::new_symbol("compileTheWorld", CHECK_ABORT);
   JavaValue result(T_VOID);
   JavaCallArguments args;
   args.push_oop(GraalRuntime::get_HotSpotGraalRuntime());
-  JavaCalls::call_special(&result, klass, compileTheWorld, vmSymbols::void_method_signature(), &args, THREAD);
-  GUARANTEE_NO_PENDING_EXCEPTION("Error while calling compile_the_world");
+  JavaCalls::call_special(&result, klass, compileTheWorld, vmSymbols::void_method_signature(), &args, CHECK_ABORT);
 }
 #endif
--- a/src/share/vm/graal/graalRuntime.cpp	Tue Jul 08 20:19:34 2014 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Thu Jul 10 19:36:27 2014 +0200
@@ -62,7 +62,9 @@
 
     env->RegisterNatives(c2vmClass, CompilerToVM_methods, CompilerToVM_methods_count());
   }
-  GUARANTEE_NO_PENDING_EXCEPTION("Could not register natives");
+  if (HAS_PENDING_EXCEPTION) {
+    abort_on_pending_exception(PENDING_EXCEPTION, "Could not register natives");
+  }
 }
 
 BufferBlob* GraalRuntime::initialize_buffer_blob() {
@@ -652,27 +654,25 @@
 
 // private static TruffleRuntime Truffle.createRuntime()
 JVM_ENTRY(jobject, JVM_CreateTruffleRuntime(JNIEnv *env, jclass c))
-  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime", THREAD);
+  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime", CHECK_NULL);
   KlassHandle klass = GraalRuntime::resolve_or_fail(name, CHECK_NULL);
 
-  TempNewSymbol makeInstance = SymbolTable::new_symbol("makeInstance", THREAD);
-  TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime;", THREAD);
+  TempNewSymbol makeInstance = SymbolTable::new_symbol("makeInstance", CHECK_NULL);
+  TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime;", CHECK_NULL);
   JavaValue result(T_OBJECT);
-  JavaCalls::call_static(&result, klass, makeInstance, sig, THREAD);
-  GUARANTEE_NO_PENDING_EXCEPTION("Couldn't initialize HotSpotTruffleRuntime");
+  JavaCalls::call_static(&result, klass, makeInstance, sig, CHECK_NULL);
   return JNIHandles::make_local((oop) result.get_jobject());
 JVM_END
 
 Handle GraalRuntime::get_HotSpotGraalRuntime() {
   if (JNIHandles::resolve(_HotSpotGraalRuntime_instance) == NULL) {
     Thread* THREAD = Thread::current();
-    TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", THREAD);
+    TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", CHECK_ABORT_(Handle()));
     KlassHandle klass = load_required_class(name);
-    TempNewSymbol runtime = SymbolTable::new_symbol("runtime", THREAD);
-    TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;", THREAD);
+    TempNewSymbol runtime = SymbolTable::new_symbol("runtime", CHECK_ABORT_(Handle()));
+    TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;", CHECK_ABORT_(Handle()));
     JavaValue result(T_OBJECT);
-    JavaCalls::call_static(&result, klass, runtime, sig, THREAD);
-    GUARANTEE_NO_PENDING_EXCEPTION("Couldn't initialize HotSpotGraalRuntime");
+    JavaCalls::call_static(&result, klass, runtime, sig, CHECK_ABORT_(Handle()));
     _HotSpotGraalRuntime_instance = JNIHandles::make_global((oop) result.get_jobject());
   }
   return Handle(JNIHandles::resolve_non_null(_HotSpotGraalRuntime_instance));
@@ -698,9 +698,8 @@
     // We now load and initialize HotSpotOptions which in turn
     // causes argument parsing to be redone with better error messages.
     CLEAR_PENDING_EXCEPTION;
-    TempNewSymbol name = SymbolTable::new_symbol("Lcom/oracle/graal/hotspot/HotSpotOptions;", THREAD);
-    instanceKlassHandle hotSpotOptionsClass = resolve_or_fail(name, THREAD);
-    GUARANTEE_NO_PENDING_EXCEPTION("Error in check_arguments");
+    TempNewSymbol name = SymbolTable::new_symbol("Lcom/oracle/graal/hotspot/HotSpotOptions;", CHECK_ABORT_(JNI_ERR));
+    instanceKlassHandle hotSpotOptionsClass = resolve_or_fail(name, CHECK_ABORT_(JNI_ERR));
 
     parse_arguments(hotSpotOptionsClass, THREAD);
     assert(HAS_PENDING_EXCEPTION, "must be");
@@ -884,8 +883,8 @@
     }
   }
 
-  TempNewSymbol setOption = SymbolTable::new_symbol("setOption", THREAD);
-  TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", THREAD);
+  TempNewSymbol setOption = SymbolTable::new_symbol("setOption", CHECK);
+  TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", CHECK);
   JavaValue result(T_VOID);
   JavaCallArguments args;
   args.push_oop(name_handle());
@@ -897,7 +896,7 @@
 }
 
 Handle GraalRuntime::get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS) {
-  TempNewSymbol name = SymbolTable::new_symbol(declaringClass, THREAD);
+  TempNewSymbol name = SymbolTable::new_symbol(declaringClass, CHECK_NH);
   Klass* klass = resolve_or_fail(name, CHECK_NH);
 
   // The class has been loaded so the field and signature should already be in the symbol
@@ -920,7 +919,7 @@
 }
 
 Handle GraalRuntime::create_Service(const char* name, TRAPS) {
-  TempNewSymbol kname = SymbolTable::new_symbol(name, THREAD);
+  TempNewSymbol kname = SymbolTable::new_symbol(name, CHECK_NH);
   Klass* k = resolve_or_fail(kname, CHECK_NH);
   instanceKlassHandle klass(THREAD, k);
   klass->initialize(CHECK_NH);
@@ -935,13 +934,12 @@
   if (_HotSpotGraalRuntime_instance != NULL) {
     JavaThread* THREAD = JavaThread::current();
     HandleMark hm(THREAD);
-    TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", THREAD);
+    TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", CHECK_ABORT);
     KlassHandle klass = load_required_class(name);
     JavaValue result(T_VOID);
     JavaCallArguments args;
     args.push_oop(get_HotSpotGraalRuntime());
-    JavaCalls::call_special(&result, klass, vmSymbols::shutdown_method_name(), vmSymbols::void_method_signature(), &args, THREAD);
-    GUARANTEE_NO_PENDING_EXCEPTION("Error while calling shutdown");
+    JavaCalls::call_special(&result, klass, vmSymbols::shutdown_method_name(), vmSymbols::void_method_signature(), &args, CHECK_ABORT);
 
     JNIHandles::destroy_global(_HotSpotGraalRuntime_instance);
     _HotSpotGraalRuntime_instance = NULL;
@@ -962,17 +960,12 @@
 
 oop GraalRuntime::compute_graal_class_loader(TRAPS) {
   assert(UseGraalClassLoader, "must be");
-  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/loader/Factory", THREAD);
-  KlassHandle klass = SystemDictionary::resolve_or_null(name, THREAD);
-  if (klass.is_null()) {
-    tty->print_cr("Could not load class %s", name->as_C_string());
-    vm_abort(false);
-  }
+  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/loader/Factory", CHECK_NULL);
+  KlassHandle klass = SystemDictionary::resolve_or_null(name, CHECK_NULL);
 
-  TempNewSymbol getClassLoader = SymbolTable::new_symbol("newClassLoader", THREAD);
+  TempNewSymbol getClassLoader = SymbolTable::new_symbol("newClassLoader", CHECK_NULL);
   JavaValue result(T_OBJECT);
-  JavaCalls::call_static(&result, klass, getClassLoader, vmSymbols::void_classloader_signature(), THREAD);
-  GUARANTEE_NO_PENDING_EXCEPTION("Couldn't initialize HotSpotGraalRuntime");
+  JavaCalls::call_static(&result, klass, getClassLoader, vmSymbols::void_classloader_signature(), CHECK_NULL);
   return (oop) result.get_jobject();
 }
 
--- a/src/share/vm/graal/graalRuntime.hpp	Tue Jul 08 20:19:34 2014 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Thu Jul 10 19:36:27 2014 +0200
@@ -139,11 +139,23 @@
    */
   static void call_printStackTrace(Handle exception, Thread* thread);
 
-#define GUARANTEE_NO_PENDING_EXCEPTION(error_message) do { \
-    if (HAS_PENDING_EXCEPTION) { \
-      GraalRuntime::abort_on_pending_exception(PENDING_EXCEPTION, error_message); \
-    } \
-  } while (0);
+#define CHECK_ABORT THREAD); \
+  if (HAS_PENDING_EXCEPTION) { \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    GraalRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \
+    return; \
+  } \
+  (void)(0
+
+#define CHECK_ABORT_(result) THREAD); \
+  if (HAS_PENDING_EXCEPTION) { \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    GraalRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \
+    return result; \
+  } \
+  (void)(0
 
   /**
    * Same as SystemDictionary::resolve_or_null but uses the Graal loader.
--- a/src/share/vm/runtime/thread.cpp	Tue Jul 08 20:19:34 2014 +0200
+++ b/src/share/vm/runtime/thread.cpp	Thu Jul 10 19:36:27 2014 +0200
@@ -3679,7 +3679,9 @@
   // anymore. We call vm_exit_during_initialization directly instead.
   SystemDictionary::compute_java_system_loader(THREAD);
 #ifdef GRAAL
-  SystemDictionary::initialize_preloaded_graal_classes(THREAD);
+  if (!HAS_PENDING_EXCEPTION) {
+    SystemDictionary::initialize_preloaded_graal_classes(THREAD);
+  }
 #endif
   if (HAS_PENDING_EXCEPTION) {
     vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));