changeset 5209:7378314d3e06

Merge
author Gilles Duboscq <duboscq@ssw.jku.at>
date Fri, 06 Apr 2012 17:58:00 +0200
parents ae5504e366df (diff) 887b45f6aa02 (current diff)
children e3e7542d78b7
files
diffstat 23 files changed, 531 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Apr 06 17:58:00 2012 +0200
@@ -128,46 +128,38 @@
 
         new PhiStampPhase().apply(graph);
 
+        if (GraalOptions.ProbabilityAnalysis && graph.start().probability() == 0) {
+            new ComputeProbabilityPhase().apply(graph);
+        }
+
+        if (GraalOptions.PropagateTypes) {
+            new PropagateTypeCachePhase(target, runtime, assumptions).apply(graph);
+        }
+
         if (GraalOptions.OptCanonicalizer) {
             new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
         }
 
-        if (GraalOptions.ProbabilityAnalysis && graph.start().probability() == 0) {
-            new ComputeProbabilityPhase().apply(graph);
-        }
-
         if (GraalOptions.Intrinsify) {
             new IntrinsificationPhase(runtime).apply(graph);
         }
 
-        if (GraalOptions.PropagateTypes) {
-            if (GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
-            }
-
-            new PropagateTypeCachePhase(target, runtime, assumptions).apply(graph);
-        }
-
         if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) {
             new InliningPhase(target, runtime, null, assumptions, cache, plan, optimisticOpts).apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
             new PhiStampPhase().apply(graph);
-        }
+            if (GraalOptions.PropagateTypes) {
+                new PropagateTypeCachePhase(target, runtime, assumptions).apply(graph);
+            }
 
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+            if (GraalOptions.OptCanonicalizer) {
+                new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+            }
         }
 
-        if (GraalOptions.PropagateTypes) {
-            new PropagateTypeCachePhase(target, runtime, assumptions).apply(graph);
-        }
 
         plan.runPhases(PhasePosition.HIGH_LEVEL, graph);
 
-        if (GraalOptions.OptLoops) {
-            new SafepointPollingEliminationPhase().apply(graph);
-        }
-
         if (GraalOptions.EscapeAnalysis && !plan.isPhaseDisabled(EscapeAnalysisPhase.class)) {
             new EscapeAnalysisPhase(target, runtime, assumptions, cache, plan, optimisticOpts).apply(graph);
             new PhiStampPhase().apply(graph);
@@ -175,7 +167,9 @@
                 new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
             }
         }
-
+        if (GraalOptions.OptLoops) {
+            new SafepointPollingEliminationPhase().apply(graph);
+        }
         if (GraalOptions.OptGVN) {
             new GlobalValueNumberingPhase().apply(graph);
         }
@@ -197,6 +191,9 @@
         if (GraalOptions.PropagateTypes) {
             new PropagateTypeCachePhase(target, runtime, assumptions).apply(graph);
         }
+        if (GraalOptions.OptCanonicalizer) {
+            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+        }
         if (GraalOptions.OptGVN) {
             new GlobalValueNumberingPhase().apply(graph);
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Fri Apr 06 17:58:00 2012 +0200
@@ -143,6 +143,7 @@
     public static boolean PrintAssembly                      = ____;
     public static boolean PrintCodeBytes                     = ____;
     public static int     PrintAssemblyBytesPerLine          = 16;
+    public static boolean PrintBailout                       = ____;
     public static int     TraceLinearScanLevel               = 0;
     public static boolean TraceRegisterAllocation            = false;
     public static int     TraceLIRGeneratorLevel             = 0;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Fri Apr 06 17:58:00 2012 +0200
@@ -860,7 +860,7 @@
         for (int operandNum = 0; operandNum < blockData.get(ir.cfg.getStartBlock()).liveIn.size(); operandNum++) {
             if (blockData.get(ir.cfg.getStartBlock()).liveIn.get(operandNum)) {
                 CiValue operand = operandFor(operandNum);
-                TTY.println(" var %d; operand=%s", operandNum, operand.toString());
+                TTY.println(" var %d; operand=%s; node=%s", operandNum, operand.toString(), gen.valueForOperand(operand));
 
                 for (int j = 0; j < numBlocks; j++) {
                     Block block = blockAt(j);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Fri Apr 06 17:58:00 2012 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.virtual.*;
 
 public class DebugInfoBuilder {
@@ -54,7 +55,13 @@
             FrameState current = topState;
             do {
                 for (Node n : current.virtualObjectMappings()) {
-                    VirtualObjectFieldNode field = (VirtualObjectFieldNode) n;
+                    Node p = n;
+                    while (p instanceof PhiNode) {
+                        PhiNode phi = (PhiNode) p;
+                        assert phi.type() == PhiType.Virtual;
+                        p = phi.valueAt(0);
+                    }
+                    VirtualObjectFieldNode field = (VirtualObjectFieldNode) p;
                     // null states occur for objects with 0 fields
                     if (field != null && !objectStates.containsKey(field.object())) {
                         objectStates.put(field.object(), field);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Apr 06 17:58:00 2012 +0200
@@ -27,6 +27,7 @@
 import static com.oracle.max.cri.ci.CiValue.*;
 
 import java.util.*;
+import java.util.Map.Entry;
 
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.util.*;
@@ -173,6 +174,15 @@
         return nodeOperands.get(node);
     }
 
+    public ValueNode valueForOperand(CiValue value) {
+        for (Entry<Node, CiValue> entry : nodeOperands.entries()) {
+            if (entry.getValue() == value) {
+                return (ValueNode) entry.getKey();
+            }
+        }
+        return null;
+    }
+
     /**
      * Creates a new {@linkplain Variable variable}.
      * @param kind The kind of the new variable.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Fri Apr 06 17:58:00 2012 +0200
@@ -130,8 +130,12 @@
 
         @Override
         public void loopEnds(LoopBeginNode loopBegin, List<BlockExitState> loopEndStates) {
-            while (!(virtualObjectField instanceof PhiNode)) {
-                virtualObjectField = ((VirtualObjectFieldNode) virtualObjectField).lastState();
+            while (!loopBegin.isPhiAtMerge(virtualObjectField)) {
+                if (virtualObjectField instanceof PhiNode) {
+                    virtualObjectField = ((PhiNode) virtualObjectField).valueAt(0);
+                } else {
+                    virtualObjectField = ((VirtualObjectFieldNode) virtualObjectField).lastState();
+                }
             }
             for (BlockExitState loopEndState : loopEndStates) {
                 ((PhiNode) virtualObjectField).addInput(loopEndState.virtualObjectField);
@@ -195,7 +199,17 @@
                         }
                         if (!curNode.isDeleted() && curNode instanceof StateSplit && ((StateSplit) curNode).stateAfter() != null) {
                             if (state.virtualObjectField != null) {
-                                ((StateSplit) curNode).stateAfter().addVirtualObjectMapping(state.virtualObjectField);
+                                ValueNode v = state.virtualObjectField;
+                                if (curNode instanceof LoopBeginNode) {
+                                    while (!((LoopBeginNode) curNode).isPhiAtMerge(v)) {
+                                        if (v instanceof PhiNode) {
+                                            v = ((PhiNode) v).valueAt(0);
+                                        } else {
+                                            v = ((VirtualObjectFieldNode) v).lastState();
+                                        }
+                                    }
+                                }
+                                ((StateSplit) curNode).stateAfter().addVirtualObjectMapping(v);
                             }
                         }
                     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Fri Apr 06 17:58:00 2012 +0200
@@ -132,8 +132,12 @@
         } catch (CiBailout bailout) {
             Debug.metric("Bailouts").increment();
             if (GraalOptions.ExitVMOnBailout) {
+                TTY.cachedOut.println(CiUtil.format("%H.%n(%p)", method));
                 bailout.printStackTrace(TTY.cachedOut);
                 System.exit(-1);
+            } else if (GraalOptions.PrintBailout) {
+                TTY.cachedOut.println(CiUtil.format("%H.%n(%p)", method));
+                bailout.printStackTrace(TTY.cachedOut);
             }
         } catch (Throwable t) {
             if (GraalOptions.ExitVMOnException) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop15.java	Fri Apr 06 17:58:00 2012 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.jtt.loop;
+
+import org.junit.*;
+
+public class Loop15 {
+
+    public static int test(int arg) {
+        Object o = null;
+        int result = 10;
+        for (int k = 0; k < arg; ++k) {
+            if (o == null) {
+                o = new Object();
+            }
+            if (k >= 5) {
+                break;
+            }
+            result++;
+        }
+        return result + (o == null ? 0 : 1);
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertEquals(16, test(5));
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        Assert.assertEquals(10, test(0));
+    }
+
+    @Test
+    public void run2() throws Throwable {
+        Assert.assertEquals(12, test(1));
+    }
+
+    @Test
+    public void run3() throws Throwable {
+        Assert.assertEquals(16, test(10));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop16.java	Fri Apr 06 17:58:00 2012 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+// Checkstyle: stop
+package com.oracle.graal.jtt.loop;
+
+import org.junit.*;
+
+/*
+ * Tests exiting 2 loops at the same time with escape-analysed values flowing out of loops
+ */
+public class Loop16 {
+
+    public int a;
+    public int b;
+    public int c;
+
+    public static int test(int count) {
+        return new Loop16().run(count);
+    }
+
+    public int run(int count) {
+    l1: for (int i = 0; i <= count; i++) {
+            if (i > 5) {
+                for (int j = 0; j < i; j++) {
+                    a += i;
+                    if (a > 500) {
+                        break l1;
+                    }
+                }
+            } else if (i > 7) {
+                b += i;
+            } else {
+                    c += i;
+            }
+        }
+        return a + b + c;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertEquals(526, test(40));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop17.java	Fri Apr 06 17:58:00 2012 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+// Checkstyle: stop
+package com.oracle.graal.jtt.loop;
+
+import org.junit.*;
+
+/*
+ * Test around an object that escapes directly from inside a loop (no virtual phi on the loop)
+ */
+public class Loop17 {
+
+    private static class L {
+        public int a;
+        public int b;
+        public int c;
+        public L(int a, int b, int c) {
+            this.a = a;
+            this.b = b;
+            this.c = c;
+        }
+    }
+
+
+    public static int test(int count) {
+        int i = 0;
+        L l;
+        do {
+            l = new L(i, i+1, i+2);
+        } while (++i < count);
+
+        return l.a + l.b * 10 + l.c * 100;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertEquals(543, test(new L(4,4,4).a));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopLastIndexOf.java	Fri Apr 06 17:58:00 2012 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.jtt.loop;
+
+import org.junit.*;
+
+/*
+ * see java.lang.String.lastIndexOf(char[], int, int, char[], int ,int, int)
+ */
+public class LoopLastIndexOf {
+
+    private final char[] v1 = new char[]{'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'};
+    private final char[] v2 = new char[]{'d', 'a'};
+    private final char[] v3 = new char[]{'d', 'b', 'c'};
+    private final char[] v4 = new char[]{'z', 'a', 'b', 'c'};
+
+    public static int test(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex) {
+        int rightIndex = sourceCount - targetCount;
+        if (fromIndex < 0) {
+            return -1;
+        }
+        if (fromIndex > rightIndex) {
+            fromIndex = rightIndex;
+        }
+        /* Empty string always matches. */
+        if (targetCount == 0) {
+            return fromIndex;
+        }
+
+        int strLastIndex = targetOffset + targetCount - 1;
+        char strLastChar = target[strLastIndex];
+        int min = sourceOffset + targetCount - 1;
+        int i = min + fromIndex;
+
+        startSearchForLastChar: while (true) {
+            while (i >= min && source[i] != strLastChar) {
+                i--;
+            }
+            if (i < min) {
+                return -1;
+            }
+            int j = i - 1;
+            int start = j - (targetCount - 1);
+            int k = strLastIndex - 1;
+
+            while (j > start) {
+                if (source[j--] != target[k--]) {
+                    i--;
+                    continue startSearchForLastChar;
+                }
+            }
+            return start - sourceOffset + 1;
+        }
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertEquals(7, test(v1, 0, v1.length, v2, 0, v2.length, 10));
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        Assert.assertEquals(-1, test(v1, 0, v1.length, v3, 0, v3.length, 10));
+    }
+
+    @Test
+    public void run2() throws Throwable {
+        Assert.assertEquals(-1, test(v1, 0, v1.length, v4, 0, v4.length, 10));
+    }
+
+    @Test
+    public void run3() throws Throwable {
+        Assert.assertEquals(-1, test(v1, 1, v1.length - 1, v3, 0, v3.length, 10));
+    }
+
+    @Test(expected = ArrayIndexOutOfBoundsException.class)
+    public void run4() throws Throwable {
+        Assert.assertEquals(-1, test(v1, 1, v1.length, v3, 0, v3.length, 10));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java	Fri Apr 06 17:58:00 2012 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.jtt.loop;
+
+import org.junit.*;
+
+public class LoopParseLong {
+
+    public static long test(String s, int radix) throws NumberFormatException {
+        if (s == null) {
+            throw new NumberFormatException("null");
+        }
+        if (radix < Character.MIN_RADIX) {
+            throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX");
+        }
+        if (radix > Character.MAX_RADIX) {
+            throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX");
+        }
+        long result = 0;
+        boolean negative = false;
+        int i = 0;
+        int len = s.length();
+        long limit = -Long.MAX_VALUE;
+        long multmin;
+        int digit;
+        if (len > 0) {
+            char firstChar = s.charAt(0);
+            if (firstChar < '0') {
+                if (firstChar == '-') {
+                    negative = true;
+                    limit = Long.MIN_VALUE;
+                } else if (firstChar != '+') {
+                    throw new NumberFormatException();
+                }
+                if (len == 1) {
+                    throw new NumberFormatException();
+                }
+                i++;
+            }
+            multmin = limit / radix;
+            while (i < len) {
+                digit = Character.digit(s.charAt(i++), radix);
+                if (digit < 0) {
+                    throw new NumberFormatException();
+                }
+                if (result < multmin) {
+                    throw new NumberFormatException();
+                }
+                result *= radix;
+                if (result < limit + digit) {
+                    throw new NumberFormatException();
+                }
+                result -= digit;
+            }
+        } else {
+            throw new NumberFormatException();
+        }
+        return negative ? result : -result;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertEquals(Character.digit('7', 10), test("7", 10));
+        Assert.assertEquals(-100, test("-100", 10));
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/CFGVerifier.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/CFGVerifier.java	Fri Apr 06 17:58:00 2012 +0200
@@ -46,7 +46,7 @@
                 assert dominated.getDominator() == block;
             }
 
-            assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().header == block;
+            assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().header == block : block.beginNode;
         }
 
         if (cfg.getLoops() != null) {
@@ -58,8 +58,16 @@
 
                     Loop blockLoop = block.getLoop();
                     while (blockLoop != loop) {
+                        assert blockLoop != null;
                         blockLoop = blockLoop.parent;
-                        assert blockLoop != null;
+                    }
+
+                    if (!(block.isLoopHeader() && block.getLoop() == loop)) {
+                        for (Block pred : block.getPredecessors()) {
+                            if (!loop.blocks.contains(pred)) {
+                                return false;
+                            }
+                        }
                     }
                 }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Fri Apr 06 17:58:00 2012 +0200
@@ -73,17 +73,27 @@
         }
     }
 
-    public void evacuateGuards() {
+    public void evacuateGuards(FixedNode evacuateFrom) {
         if (!usages().isEmpty()) {
-            Node prevBegin = predecessor();
+            Node prevBegin = evacuateFrom;
             assert prevBegin != null;
             while (!(prevBegin instanceof BeginNode)) {
                 prevBegin = prevBegin.predecessor();
             }
-            replaceAtUsages(prevBegin);
+            for (Node anchored : anchored().snapshot()) {
+                anchored.replaceFirstInput(this, prevBegin);
+            }
         }
     }
 
+    public void prepareDelete() {
+        prepareDelete((FixedNode) predecessor());
+    }
+
+    public void prepareDelete(FixedNode evacuateFrom) {
+        evacuateGuards(evacuateFrom);
+    }
+
     @Override
     public boolean verify() {
         assertTrue(predecessor() != null || this == ((StructuredGraph) graph()).start() || this instanceof MergeNode, "begin nodes must be connected");
@@ -98,4 +108,8 @@
     public NodeIterable<GuardNode> guards() {
         return usages().filter(GuardNode.class);
     }
+
+    public NodeIterable<Node> anchored() {
+        return usages();
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Fri Apr 06 17:58:00 2012 +0200
@@ -161,14 +161,16 @@
         EndNode falseEnd = (EndNode) falseSuccessor.next();
         assert trueEnd.merge() == falseEnd.merge();
 
+        FixedWithNextNode pred = (FixedWithNextNode) predecessor();
         MergeNode merge = trueEnd.merge();
+        merge.prepareDelete(pred);
         assert merge.usages().isEmpty();
 
         FixedNode next = merge.next();
         merge.setNext(null);
         setTrueSuccessor(null);
         setFalseSuccessor(null);
-        ((FixedWithNextNode) predecessor()).setNext(next);
+        pred.setNext(next);
         safeDelete();
         trueSuccessor.safeDelete();
         falseSuccessor.safeDelete();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Fri Apr 06 17:58:00 2012 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import static com.oracle.graal.graph.iterators.NodePredicates.*;
+
 import java.util.*;
 
 import com.oracle.graal.graph.*;
@@ -49,8 +51,13 @@
         return usages().filter(LoopEndNode.class);
     }
 
+    @Override
+    public NodeIterable<Node> anchored() {
+        return super.anchored().filter(isNotA(LoopEndNode.class));
+    }
+
     public List<LoopEndNode> orderedLoopEnds() {
-        List<LoopEndNode> snapshot = usages().filter(LoopEndNode.class).snapshot();
+        List<LoopEndNode> snapshot = loopEnds().snapshot();
         Collections.sort(snapshot, new Comparator<LoopEndNode>() {
             @Override
             public int compare(LoopEndNode o1, LoopEndNode o2) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Fri Apr 06 17:58:00 2012 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.util.*;
 
 /**
  * Denotes the merging of multiple control-flow paths.
@@ -115,12 +116,22 @@
     }
 
     public NodeIterable<PhiNode> phis() {
-        return this.usages().filter(new NodePredicate() {
+        return this.usages().filter(PhiNode.class).filter(new NodePredicate() {
             @Override
             public boolean apply(Node n) {
-                return n instanceof PhiNode && ((PhiNode) n).merge() == MergeNode.this;
+                return ((PhiNode) n).merge() == MergeNode.this;
             }
-        }).filter(PhiNode.class);
+        });
+    }
+
+    @Override
+    public NodeIterable<Node> anchored() {
+        return super.anchored().filter(isNotA(PhiNode.class).or(new NodePredicate() {
+            @Override
+            public boolean apply(Node n) {
+                return ((PhiNode) n).merge() != MergeNode.this;
+            }
+        }));
     }
 
     @Override
@@ -136,7 +147,9 @@
                     }
                 }
             }
-            Debug.log("Split %s into loop ends for %s", this, begin);
+            FixedNode evacuateAnchoredTo = new ComputeImmediateDominator(this).compute();
+            Debug.log("Split %s into loop ends for %s. Evacuate to %s", this, begin, evacuateAnchoredTo);
+            this.prepareDelete(evacuateAnchoredTo);
             int numEnds = this.forwardEndCount();
             StructuredGraph graph = (StructuredGraph) graph();
             for (int i = 0; i < numEnds - 1; i++) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Fri Apr 06 17:58:00 2012 +0200
@@ -33,22 +33,15 @@
  * and a variable.
  */
 public final class PhiNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType {
-
-    @Input(notDataflow = true) private MergeNode merge;
-
-    @Input private final NodeInputList<ValueNode> values = new NodeInputList<>(this);
-
-    public MergeNode merge() {
-        return merge;
-    }
-
     public static enum PhiType {
         Value, // normal value phis
         Memory, // memory phis
         Virtual // phis used for VirtualObjectField merges
     }
 
-    private final PhiType type;
+    @Input(notDataflow = true) private MergeNode merge;
+    @Input private final NodeInputList<ValueNode> values = new NodeInputList<>(this);
+    @Data private final PhiType type;
 
     public PhiNode(CiKind kind, MergeNode merge, PhiType type) {
         super(StampFactory.forKind(kind));
@@ -60,6 +53,10 @@
         return type;
     }
 
+    public MergeNode merge() {
+        return merge;
+    }
+
     public NodeInputList<ValueNode> values() {
         return values;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Fri Apr 06 17:58:00 2012 +0200
@@ -168,6 +168,9 @@
 
     public void removeFixed(FixedWithNextNode node) {
         assert node != null;
+        if (node instanceof BeginNode) {
+            ((BeginNode) node).prepareDelete();
+        }
         assert node.usages().isEmpty() : node + " " + node.usages();
         FixedNode next = node.next();
         node.setNext(null);
@@ -208,15 +211,11 @@
         assert node.usages().isEmpty();
         assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
         BeginNode begin = node.blockSuccessor(survivingSuccessor);
-        begin.evacuateGuards();
-        FixedNode next = begin.next();
-        begin.setNext(null);
         for (int i = 0; i < node.blockSuccessorCount(); i++) {
             node.setBlockSuccessor(i, null);
         }
-        node.replaceAtPredecessors(next);
+        node.replaceAtPredecessors(begin);
         node.safeDelete();
-        begin.safeDelete();
     }
 
     public void removeSplitPropagate(ControlSplitNode node, int survivingSuccessor) {
@@ -224,9 +223,6 @@
         assert node.usages().isEmpty();
         assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
         BeginNode begin = node.blockSuccessor(survivingSuccessor);
-        begin.evacuateGuards();
-        FixedNode next = begin.next();
-        begin.setNext(null);
         for (int i = 0; i < node.blockSuccessorCount(); i++) {
             BeginNode successor = node.blockSuccessor(i);
             node.setBlockSuccessor(i, null);
@@ -234,10 +230,9 @@
                 GraphUtil.killCFG(successor);
             }
         }
-        if (next.isAlive()) {
-            node.replaceAtPredecessors(next);
+        if (begin.isAlive()) {
+            node.replaceAtPredecessors(begin);
             node.safeDelete();
-            begin.safeDelete();
         } else {
             assert node.isDeleted();
         }
@@ -257,31 +252,23 @@
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
         assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
         BeginNode begin = node.blockSuccessor(survivingSuccessor);
-        begin.evacuateGuards();
-        FixedNode next = begin.next();
-        begin.setNext(null);
         for (int i = 0; i < node.blockSuccessorCount(); i++) {
             node.setBlockSuccessor(i, null);
         }
-        replacement.setNext(next);
+        replacement.setNext(begin);
         node.replaceAndDelete(replacement);
-        begin.safeDelete();
     }
 
     public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, int survivingSuccessor) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
         assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
         BeginNode begin = node.blockSuccessor(survivingSuccessor);
-        begin.evacuateGuards();
-        FixedNode next = begin.next();
-        begin.setNext(null);
         for (int i = 0; i < node.blockSuccessorCount(); i++) {
             node.setBlockSuccessor(i, null);
         }
-        node.replaceAtPredecessors(next);
+        node.replaceAtPredecessors(begin);
         node.replaceAtUsages(replacement);
         node.safeDelete();
-        begin.safeDelete();
     }
 
     public void addAfterFixed(FixedWithNextNode node, FixedWithNextNode newNode) {
@@ -326,13 +313,7 @@
         FixedNode sux = merge.next();
         FrameState stateAfter = merge.stateAfter();
         // evacuateGuards
-        Node prevBegin = singleEnd.predecessor();
-        assert prevBegin != null;
-        while (!(prevBegin instanceof BeginNode)) {
-            prevBegin = prevBegin.predecessor();
-        }
-        merge.replaceAtUsages(prevBegin);
-
+        merge.prepareDelete((FixedNode) singleEnd.predecessor());
         merge.safeDelete();
         if (stateAfter != null && stateAfter.usages().isEmpty()) {
             stateAfter.safeDelete();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Fri Apr 06 17:58:00 2012 +0200
@@ -52,7 +52,7 @@
                 return x();
             }
             if (c == 0) {
-                return ConstantNode.forInt(0, graph());
+                return ConstantNode.defaultForKind(kind(), graph());
             }
             if (c > 0 && CiUtil.isPowerOf2(c)) {
                 return graph().unique(new LeftShiftNode(kind(), x(), ConstantNode.forInt(CiUtil.log2(c), graph())));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Fri Apr 06 17:58:00 2012 +0200
@@ -36,6 +36,8 @@
 
     @Input private ValueNode index;
     @Input private ValueNode length;
+    @Data private final CiKind elementType;
+    private final long leafGraphId;
 
     public ValueNode index() {
         return index;
@@ -45,9 +47,6 @@
         return length;
     }
 
-    private final CiKind elementType;
-    private final long leafGraphId;
-
     /**
      * Create an new AccessIndexedNode.
      * @param kind the result kind of the access
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Fri Apr 06 17:58:00 2012 +0200
@@ -27,8 +27,10 @@
 import java.util.*;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.virtual.*;
 
 public class GraphUtil {
 
@@ -40,7 +42,11 @@
             killEnd(end);
         } else {
             // Normal control flow node.
-            for (Node successor : node.successors().snapshot()) {
+            /* We do not take a successor snapshot because this iterator supports concurrent modifications
+             * as long as they do not change the size of the successor list. Not tasking a snapshot allows
+             * us to see modifications to other branches that may happen while processing one branch.
+             */
+            for (Node successor : node.successors()) {
                 killCFG((FixedNode) successor);
             }
         }
@@ -50,6 +56,7 @@
     private static void killEnd(EndNode end) {
         MergeNode merge = end.merge();
         merge.removeEnd(end);
+        StructuredGraph graph = (StructuredGraph) end.graph();
         if (merge instanceof LoopBeginNode && merge.forwardEndCount() == 0) { //dead loop
             for (PhiNode phi : merge.phis().snapshot()) {
                 propagateKill(phi);
@@ -63,15 +70,19 @@
             killCFG(begin.next());
             begin.safeDelete();
         } else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) { // not a loop anymore
-            ((StructuredGraph) end.graph()).reduceDegenerateLoopBegin((LoopBeginNode) merge);
+            graph.reduceDegenerateLoopBegin((LoopBeginNode) merge);
         } else if (merge.phiPredecessorCount() == 1) { // not a merge anymore
-            ((StructuredGraph) end.graph()).reduceTrivialMerge(merge);
+            graph.reduceTrivialMerge(merge);
         }
     }
 
+    public static NodePredicate isFloatingNode() {
+        return isA(FloatingNode.class).or(CallTargetNode.class).or(FrameState.class).or(VirtualObjectFieldNode.class).or(VirtualObjectNode.class);
+    }
+
     public static void propagateKill(Node node) {
         if (node != null && node.isAlive()) {
-            List<Node> usagesSnapshot = node.usages().filter(isA(FloatingNode.class).or(CallTargetNode.class).or(FrameState.class)).snapshot();
+            List<Node> usagesSnapshot = node.usages().filter(isFloatingNode()).snapshot();
 
             // null out remaining usages
             node.replaceAtUsages(null);
@@ -91,7 +102,7 @@
     }
 
     public static void killUnusedFloatingInputs(Node node) {
-        List<Node> floatingInputs = node.inputs().filter(isA(FloatingNode.class).or(CallTargetNode.class).or(FrameState.class)).snapshot();
+        List<Node> floatingInputs = node.inputs().filter(isFloatingNode()).snapshot();
         node.safeDelete();
 
         for (Node in : floatingInputs) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java	Fri Apr 06 17:24:47 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java	Fri Apr 06 17:58:00 2012 +0200
@@ -66,6 +66,13 @@
     }
 
     @Override
+    public boolean verify() {
+        assertTrue(object != null, "No object");
+        assertTrue(input != null, "No input");
+        return super.verify();
+    }
+
+    @Override
     public Map<Object, Object> getDebugProperties() {
         Map<Object, Object> properties = super.getDebugProperties();
         properties.put("index", index);
@@ -74,7 +81,7 @@
 
     @Override
     public String toString(Verbosity verbosity) {
-        if (verbosity == Verbosity.Name && object().fields() != null) {
+        if (verbosity == Verbosity.Name && object() != null && object().fields() != null) {
             return super.toString(Verbosity.Name) + " " + object().fields()[index].name();
         } else {
             return super.toString(verbosity);