changeset 5633:bda2ebe1fc61

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sat, 16 Jun 2012 02:20:02 +0200
parents 4d0f01e9f31b (current diff) 63bd4fd90c27 (diff)
children e0aa35b489f3
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java
diffstat 55 files changed, 1995 insertions(+), 192 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Sat Jun 16 02:20:02 2012 +0200
@@ -261,7 +261,7 @@
      * Only instructions in methods whose fully qualified name contains this option will be HIR lowered.
      */
     public static String HIRLowerCheckcast = "";
-    public static String HIRLowerNewInstance = "NewInstanceTest";
+    public static String HIRLowerNewInstance = "NewInstanceTest.new";
 
     /**
      * The profiling info cache directory.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/BasicInductionVariable.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,129 @@
+/*
+ * 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.compiler.loop;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.type.*;
+
+
+public class BasicInductionVariable extends InductionVariable {
+    private PhiNode phi;
+    private ValueNode init;
+    private ValueNode rawStride;
+    private IntegerArithmeticNode op;
+
+    public BasicInductionVariable(LoopEx loop, PhiNode phi, ValueNode init, ValueNode rawStride, IntegerArithmeticNode op) {
+        super(loop);
+        this.phi = phi;
+        this.init = init;
+        this.rawStride = rawStride;
+        this.op = op;
+    }
+
+    @Override
+    public Direction direction() {
+        Stamp stamp = rawStride.stamp();
+        if (stamp instanceof IntegerStamp) {
+            IntegerStamp integerStamp = (IntegerStamp) stamp;
+            Direction dir = null;
+            if (integerStamp.lowerBound() > 0) {
+                dir = Direction.Up;
+            } else if (integerStamp.upperBound() < 0) {
+                dir =  Direction.Down;
+            }
+            if (dir != null) {
+                if (op instanceof IntegerAddNode) {
+                    return dir;
+                } else {
+                    assert op instanceof IntegerSubNode;
+                    return dir.opposite();
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public PhiNode valueNode() {
+        return phi;
+    }
+
+    @Override
+    public ValueNode initNode() {
+        return init;
+    }
+
+    @Override
+    public ValueNode strideNode() {
+        if (op instanceof IntegerAddNode) {
+            return rawStride;
+        }
+        if (op instanceof IntegerSubNode) {
+            return rawStride.graph().unique(new NegateNode(rawStride));
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    public boolean isConstantInit() {
+        return init.isConstant();
+    }
+
+    @Override
+    public boolean isConstantStride() {
+        return rawStride.isConstant();
+    }
+
+    @Override
+    public long constantInit() {
+        return init.asConstant().asLong();
+    }
+
+    @Override
+    public long constantStride() {
+        if (op instanceof IntegerAddNode) {
+            return rawStride.asConstant().asLong();
+        }
+        if (op instanceof IntegerSubNode) {
+            return -rawStride.asConstant().asLong();
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    public ValueNode extremumNode() {
+        return IntegerArithmeticNode.add(IntegerArithmeticNode.mul(strideNode(), loop.counted().maxTripCountNode()), init);
+    }
+
+    @Override
+    public boolean isConstantExtremum() {
+        return isConstantInit() && isConstantStride() && loop.counted().isConstantMaxTripCount();
+    }
+
+    @Override
+    public long constantExtremum() {
+        return constantStride() * loop.counted().constantMaxTripCount() + constantInit();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/CountedLoopInfo.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.compiler.loop;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+
+public class CountedLoopInfo {
+    private final LoopEx loop;
+    private InductionVariable iv;
+    private ValueNode end;
+
+    CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end) {
+        this.loop = loop;
+        this.iv = iv;
+        this.end = end;
+    }
+
+    public ValueNode maxTripCountNode() {
+        return IntegerArithmeticNode.div(IntegerArithmeticNode.sub(end, iv.initNode()), iv.strideNode());
+    }
+
+    public boolean isConstantMaxTripCount() {
+        return end instanceof ConstantNode && iv.isConstantInit() && iv.isConstantStride();
+    }
+
+    public long constantMaxTripCount() {
+        return (((ConstantNode) end).asConstant().asLong() - iv.constantInit()) / iv.constantStride();
+    }
+
+    public boolean isExactTripCount() {
+        return loop.loopBegin().loopExits().count() == 1;
+    }
+
+    public ValueNode exactTripCountNode() {
+        assert isExactTripCount();
+        return maxTripCountNode();
+    }
+
+    public boolean isConstantExactTripCount() {
+        assert isExactTripCount();
+        return isConstantMaxTripCount();
+    }
+
+    public long constantExactTripCount() {
+        assert isExactTripCount();
+        return constantMaxTripCount();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/DerivedOffsetInductionVariable.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,132 @@
+/*
+ * 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.compiler.loop;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+
+
+public class DerivedOffsetInductionVariable extends InductionVariable {
+    private InductionVariable base;
+    private ValueNode offset;
+    private IntegerArithmeticNode value;
+
+    public DerivedOffsetInductionVariable(LoopEx loop, InductionVariable base, ValueNode offset, IntegerArithmeticNode value) {
+        super(loop);
+        this.base = base;
+        this.offset = offset;
+        this.value = value;
+    }
+
+    @Override
+    public Direction direction() {
+        return base.direction();
+    }
+
+    @Override
+    public ValueNode valueNode() {
+        return value;
+    }
+
+    @Override
+    public boolean isConstantInit() {
+        return offset.isConstant() && base.isConstantInit();
+    }
+
+    @Override
+    public boolean isConstantStride() {
+        return base.isConstantStride();
+    }
+
+    @Override
+    public long constantInit() {
+        return op(base.constantInit(), offset.asConstant().asLong());
+    }
+
+    @Override
+    public long constantStride() {
+        if (value instanceof IntegerSubNode && base.valueNode() == value.y()) {
+            return -base.constantStride();
+        }
+        return base.constantStride();
+    }
+
+    @Override
+    public ValueNode initNode() {
+        return op(base.initNode(), offset);
+    }
+
+    @Override
+    public ValueNode strideNode() {
+        if (value instanceof IntegerSubNode && base.valueNode() == value.y()) {
+            return value.graph().unique(new NegateNode(base.strideNode()));
+        }
+        return base.strideNode();
+    }
+
+    @Override
+    public ValueNode extremumNode() {
+        return op(offset, base.extremumNode());
+    }
+
+    @Override
+    public boolean isConstantExtremum() {
+        return offset.isConstant() && base.isConstantExtremum();
+    }
+
+    @Override
+    public long constantExtremum() {
+        return op(base.constantExtremum(), offset.asConstant().asLong());
+    }
+
+    private long op(long b, long o) {
+        if (value instanceof IntegerAddNode) {
+            return b + o;
+        }
+        if (value instanceof IntegerSubNode) {
+            if (base.valueNode() == value.x()) {
+                return b - o;
+            } else {
+                assert base.valueNode() == value.y();
+                return o - b;
+            }
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    private ValueNode op(ValueNode b, ValueNode o) {
+        if (value instanceof IntegerAddNode) {
+        return IntegerArithmeticNode.add(b, o);
+        }
+        if (value instanceof IntegerSubNode) {
+            if (base.valueNode() == value.x()) {
+                return IntegerArithmeticNode.sub(b, o);
+            } else {
+                assert base.valueNode() == value.y();
+                return IntegerArithmeticNode.sub(o, b);
+            }
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/DerivedScaledInductionVariable.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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.compiler.loop;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.type.*;
+
+
+public class DerivedScaledInductionVariable extends InductionVariable {
+    private InductionVariable base;
+    private ValueNode scale;
+    private ValueNode value;
+
+    public DerivedScaledInductionVariable(LoopEx loop, InductionVariable base, ValueNode scale, ValueNode value) {
+        super(loop);
+        this.base = base;
+        this.scale = scale;
+        this.value = value;
+    }
+
+    public DerivedScaledInductionVariable(LoopEx loop, InductionVariable base, NegateNode value) {
+        super(loop);
+        this.base = base;
+        this.scale = ConstantNode.forInt(-1, value.graph());
+        this.value = value;
+    }
+
+    @Override
+    public Direction direction() {
+        Stamp stamp = scale.stamp();
+        if (stamp instanceof IntegerStamp) {
+            IntegerStamp integerStamp = (IntegerStamp) stamp;
+            if (integerStamp.lowerBound() > 0) {
+                return base.direction();
+            } else if (integerStamp.upperBound() < 0) {
+                return base.direction().opposite();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public ValueNode valueNode() {
+        return value;
+    }
+
+    @Override
+    public ValueNode initNode() {
+        return IntegerArithmeticNode.mul(base.initNode(), scale);
+    }
+
+    @Override
+    public ValueNode strideNode() {
+        return IntegerArithmeticNode.mul(base.strideNode(), scale);
+    }
+
+    @Override
+    public boolean isConstantInit() {
+        return scale.isConstant() && base.isConstantInit();
+    }
+
+    @Override
+    public boolean isConstantStride() {
+        return scale.isConstant() && base.isConstantStride();
+    }
+
+    @Override
+    public long constantInit() {
+        return base.constantInit() * scale.asConstant().asLong();
+    }
+
+    @Override
+    public long constantStride() {
+        return base.constantStride() * scale.asConstant().asLong();
+    }
+
+    @Override
+    public ValueNode extremumNode() {
+        return IntegerArithmeticNode.mul(base.extremumNode(), scale);
+    }
+
+    @Override
+    public boolean isConstantExtremum() {
+        return scale.isConstant() && base.isConstantExtremum();
+    }
+
+    @Override
+    public long constantExtremum() {
+        return base.constantExtremum() * scale.asConstant().asLong();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/InductionVariable.java	Sat Jun 16 02:20:02 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.compiler.loop;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+
+public abstract class InductionVariable {
+    public enum Direction {
+        Up,
+        Down;
+        public Direction opposite() {
+            switch(this) {
+                case Up: return Down;
+                case Down: return Up;
+                default: throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    protected final LoopEx loop;
+
+    public InductionVariable(LoopEx loop) {
+        this.loop = loop;
+    }
+
+    public abstract Direction direction();
+
+    public abstract ValueNode valueNode();
+
+    public abstract ValueNode initNode();
+    public abstract ValueNode strideNode();
+
+    public abstract boolean isConstantInit();
+    public abstract boolean isConstantStride();
+
+    public abstract long constantInit();
+    public abstract long constantStride();
+
+    public abstract ValueNode extremumNode();
+    public abstract boolean isConstantExtremum();
+    public abstract long constantExtremum();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/InductionVariables.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,122 @@
+/*
+ * 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.compiler.loop;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+
+
+public class InductionVariables {
+    private final LoopEx loop;
+    private Map<Node, InductionVariable> ivs;
+
+    public InductionVariables(LoopEx loop) {
+        this.loop = loop;
+        ivs = new IdentityHashMap<>();
+        findDerived(findBasic());
+    }
+
+    public InductionVariable get(ValueNode v) {
+        return ivs.get(v);
+    }
+
+    private Collection<BasicInductionVariable> findBasic() {
+        List<BasicInductionVariable> bivs = new LinkedList<>();
+        LoopBeginNode loopBegin = loop.loopBegin();
+        EndNode forwardEnd = loopBegin.forwardEnd();
+        for (PhiNode phi : loopBegin.phis()) {
+            ValueNode backValue = phi.singleBackValue();
+            if (backValue == null) {
+                continue;
+            }
+            ValueNode stride = addSub(backValue, phi);
+            if (stride != null) {
+                BasicInductionVariable biv = new BasicInductionVariable(loop, phi, phi.valueAt(forwardEnd), stride, (IntegerArithmeticNode) backValue);
+                ivs.put(phi, biv);
+                bivs.add(biv);
+            }
+        }
+        return bivs;
+    }
+
+    private void findDerived(Collection<BasicInductionVariable> bivs) {
+        Queue<InductionVariable> scanQueue = new LinkedList<InductionVariable>(bivs);
+        while (!scanQueue.isEmpty()) {
+            InductionVariable baseIv = scanQueue.remove();
+            ValueNode baseIvNode = baseIv.valueNode();
+            for (ValueNode op : baseIvNode.usages().filter(ValueNode.class)) {
+                if (loop.isOutsideLoop(op)) {
+                    continue;
+                }
+                InductionVariable iv = null;
+                ValueNode offset = addSub(op, baseIvNode);
+                ValueNode scale;
+                if (offset != null) {
+                    iv = new DerivedOffsetInductionVariable(loop, baseIv, offset, (IntegerArithmeticNode) op);
+                } else if (op instanceof NegateNode) {
+                    iv = new DerivedScaledInductionVariable(loop, baseIv, (NegateNode) op);
+                } else if ((scale = mul(op, baseIvNode)) != null) {
+                    iv = new DerivedScaledInductionVariable(loop, baseIv, scale, op);
+                }
+
+                if (iv != null) {
+                    ivs.put(op, iv);
+                    scanQueue.offer(iv);
+                }
+            }
+        }
+    }
+
+    private ValueNode addSub(ValueNode op, ValueNode base) {
+        if (op instanceof IntegerAddNode || op instanceof IntegerSubNode) {
+            IntegerArithmeticNode aritOp = (IntegerArithmeticNode) op;
+            if (aritOp.x() == base && loop.isOutsideLoop(aritOp.y())) {
+                return aritOp.y();
+            } else if (aritOp.y() == base && loop.isOutsideLoop(aritOp.x())) {
+                return aritOp.x();
+            }
+        }
+        return null;
+    }
+
+    private ValueNode mul(ValueNode op, ValueNode base) {
+        if (op instanceof IntegerMulNode) {
+            IntegerMulNode mul = (IntegerMulNode) op;
+            if (mul.x() == base && loop.isOutsideLoop(mul.y())) {
+                return mul.y();
+            } else if (mul.y() == base && loop.isOutsideLoop(mul.x())) {
+                return mul.x();
+            }
+        }
+        if (op instanceof LeftShiftNode) {
+            LeftShiftNode shift = (LeftShiftNode) op;
+            if (shift.x() == base && shift.y().isConstant()) {
+                return ConstantNode.forInt(1 << shift.y().asConstant().asInt(), base.graph());
+            }
+        }
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopEx.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopEx.java	Sat Jun 16 02:20:02 2012 +0200
@@ -30,7 +30,7 @@
     private final Loop lirLoop;
     private LoopFragmentInside inside;
     private LoopFragmentWhole whole;
-    private boolean isCounted; //TODO (gd) detect
+    private CountedLoopInfo counted; //TODO (gd) detect
     private LoopsData data;
 
     LoopEx(Loop lirLoop, LoopsData data) {
@@ -68,7 +68,7 @@
         return null;
     }
 
-    public boolean isInvariant(Node n) {
+    public boolean isOutsideLoop(Node n) {
         return !whole().contains(n);
     }
 
@@ -85,7 +85,11 @@
     }
 
     public boolean isCounted() {
-        return isCounted;
+        return counted != null;
+    }
+
+    public CountedLoopInfo counted() {
+        return counted;
     }
 
     public LoopEx parent() {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java	Sat Jun 16 02:20:02 2012 +0200
@@ -156,8 +156,9 @@
         }
         for (BeginNode earlyExit : earlyExits) {
             FrameState stateAfter = earlyExit.stateAfter();
-            assert stateAfter != null;
-            nodes.mark(stateAfter);
+            if (stateAfter != null) {
+                nodes.mark(stateAfter);
+            }
             nodes.mark(earlyExit);
             for (ValueProxyNode proxy : earlyExit.proxies()) {
                 nodes.mark(proxy);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopsData.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopsData.java	Sat Jun 16 02:20:02 2012 +0200
@@ -24,8 +24,12 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.loop.InductionVariable.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 
 public class LoopsData {
     private Map<Loop, LoopEx> lirLoopToEx = new IdentityHashMap<>();
@@ -72,4 +76,72 @@
         }
         return counted;
     }
+
+    public void detectedCountedLoops() {
+        for (LoopEx loop : loops()) {
+            InductionVariables ivs = new InductionVariables(loop);
+            LoopBeginNode loopBegin = loop.loopBegin();
+            FixedNode next = loopBegin.next();
+            if (next instanceof IfNode) {
+                IfNode ifNode = (IfNode) next;
+                boolean negated = false;
+                if (!loopBegin.isLoopExit(ifNode.falseSuccessor())) {
+                    if (!loopBegin.isLoopExit(ifNode.trueSuccessor())) {
+                        continue;
+                    }
+                    negated = true;
+                }
+                BooleanNode ifTest = ifNode.compare();
+                if (!(ifTest instanceof IntegerLessThanNode)) {
+                    if (ifTest instanceof IntegerBelowThanNode) {
+                        Debug.log("Ignored potential Counted loop at %s with |<|", loopBegin);
+                    }
+                    continue;
+                }
+                IntegerLessThanNode lessThan = (IntegerLessThanNode) ifTest;
+                Condition condition = null;
+                InductionVariable iv = null;
+                ValueNode limit = null;
+                if (loop.isOutsideLoop(lessThan.x())) {
+                    iv = ivs.get(lessThan.y());
+                    if (iv != null) {
+                        condition = lessThan.condition().mirror();
+                        limit = lessThan.x();
+                    }
+                } else if (loop.isOutsideLoop(lessThan.y())) {
+                    iv = ivs.get(lessThan.x());
+                    if (iv != null) {
+                        condition = lessThan.condition();
+                        limit = lessThan.y();
+                    }
+                }
+                if (condition == null) {
+                    continue;
+                }
+                if (negated) {
+                    condition = condition.negate();
+                }
+                boolean oneOff = false;
+                switch (condition) {
+                    case LE:
+                        oneOff = true; // fall through
+                    case LT:
+                        if (iv.direction() != Direction.Up) {
+                            continue;
+                        }
+                        break;
+                    case GE:
+                        oneOff = true; // fall through
+                    case GT:
+                        if (iv.direction() != Direction.Down) {
+                            continue;
+                        }
+                        break;
+                    default: throw GraalInternalError.shouldNotReachHere();
+                }
+                // TODO (gd)
+                Debug.log("absorb %b %s", oneOff, limit);
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Sat Jun 16 02:20:02 2012 +0200
@@ -226,6 +226,14 @@
             public PrintStream output() {
                 return output;
             }
+
+            @Override
+            public void addToContext(Object o) {
+            }
+
+            @Override
+            public void removeFromContext(Object o) {
+            }
         };
     }
 
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java	Sat Jun 16 02:20:02 2012 +0200
@@ -28,21 +28,39 @@
 
 public interface DebugConfig {
     /**
+     * Determines if logging is enabled in the {@linkplain Debug#currentScope() current debug scope}.
+     *
      * @see Debug#log(String, Object...)
      */
     boolean isLogEnabled();
 
     /**
+     * Determines if metering is enabled in the {@linkplain Debug#currentScope() current debug scope}.
+     *
      * @see Debug#metric(String)
      */
     boolean isMeterEnabled();
 
     /**
+     * Determines if dumping is enabled in the {@linkplain Debug#currentScope() current debug scope}.
+     *
      * @see Debug#dump(Object, String, Object...)
      */
     boolean isDumpEnabled();
 
     /**
+     * Adds an object the context used by this configuration to do filtering.
+     */
+    void addToContext(Object o);
+
+    /**
+     * Removes an object the context used by this configuration to do filtering.
+     *
+     * This should only removes extra context added by {@link #addToContext(Object)}.
+     */
+    void removeFromContext(Object o);
+
+    /**
      * @see Debug#timer(String)
      */
     boolean isTimeEnabled();
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Sat Jun 16 02:20:02 2012 +0200
@@ -295,7 +295,7 @@
      */
     public NodeIterable<Node> getNewNodes(int mark) {
         final int index = mark;
-        return new NodeIterable<Node>() {
+        return new AbstractNodeIterable<Node>() {
             @Override
             public Iterator<Node> iterator() {
                 return new NodeIterator(index);
@@ -308,7 +308,7 @@
      * @return an {@link Iterable} providing all the live nodes.
      */
     public NodeIterable<Node> getNodes() {
-        return new NodeIterable<Node>() {
+        return new AbstractNodeIterable<Node>() {
             @Override
             public Iterator<Node> iterator() {
                 return new NodeIterator();
@@ -385,7 +385,7 @@
      */
     public <T extends Node & IterableNodeType> NodeIterable<T> getNodes(final Class<T> type) {
         final Node start = getStartNode(type);
-        return new NodeIterable<T>() {
+        return new AbstractNodeIterable<T>() {
             @Override
             public Iterator<T> iterator() {
                 return new TypedNodeIterator<>(start);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Sat Jun 16 02:20:02 2012 +0200
@@ -28,7 +28,7 @@
 
 
 
-public final class NodeBitMap extends NodeIterable<Node>{
+public final class NodeBitMap extends AbstractNodeIterable<Node>{
     private final boolean autoGrow;
     private final BitSet bitMap;
     private final Graph graph;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputsIterable.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputsIterable.java	Sat Jun 16 02:20:02 2012 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.iterators.*;
 
-public abstract class NodeInputsIterable extends NodeIterable<Node> {
+public abstract class NodeInputsIterable extends AbstractNodeIterable<Node> {
     @Override
     public abstract NodeClassIterator iterator();
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Sat Jun 16 02:20:02 2012 +0200
@@ -25,13 +25,12 @@
 
 import com.oracle.graal.graph.iterators.*;
 
-public abstract class NodeList<T extends Node> extends NodeIterable<T> implements List<T> {
+public abstract class NodeList<T extends Node> extends AbstractList<T> implements NodeIterable<T> {
 
     protected static final Node[] EMPTY_NODE_ARRAY = new Node[0];
 
     protected Node[] nodes;
     private int size;
-    private int modCount;
     protected final int initialSize;
 
     protected NodeList() {
@@ -327,46 +326,6 @@
     }
 
     @Override
-    public boolean addAll(int index, Collection< ? extends T> c) {
-        throw new UnsupportedOperationException("not implemented");
-    }
-
-    @Override
-    public boolean removeAll(Collection< ? > c) {
-        throw new UnsupportedOperationException("not implemented");
-    }
-
-    @Override
-    public boolean retainAll(Collection< ? > c) {
-        throw new UnsupportedOperationException("not implemented");
-    }
-
-    @Override
-    public void add(int index, T element) {
-        throw new UnsupportedOperationException("not implemented");
-    }
-
-    @Override
-    public int lastIndexOf(Object o) {
-        throw new UnsupportedOperationException("not implemented");
-    }
-
-    @Override
-    public ListIterator<T> listIterator() {
-        throw new UnsupportedOperationException("not implemented");
-    }
-
-    @Override
-    public ListIterator<T> listIterator(int index) {
-        throw new UnsupportedOperationException("not implemented");
-    }
-
-    @Override
-    public List<T> subList(int fromIndex, int toIndex) {
-        throw new UnsupportedOperationException("not implemented");
-    }
-
-    @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append('[');
@@ -379,4 +338,41 @@
         sb.append(']');
         return sb.toString();
     }
+
+    @Override
+    public NodeIterable<T> until(final T u) {
+        return new FilteredNodeIterable<>(this).until(u);
+    }
+    @Override
+    public NodeIterable<T> until(final Class<? extends T> clazz) {
+        return new FilteredNodeIterable<>(this).until(clazz);
+    }
+    @Override
+    @SuppressWarnings("unchecked")
+    public <F extends T> NodeIterable<F> filter(Class<F> clazz) {
+        return (NodeIterable<F>) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz));
+    }
+    @Override
+    public NodeIterable<T> filterInterface(Class<?> iface) {
+        return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface));
+    }
+    @Override
+    public FilteredNodeIterable<T> filter(NodePredicate predicate) {
+        return new FilteredNodeIterable<>(this).and(predicate);
+    }
+    @Override
+    public FilteredNodeIterable<T> nonNull() {
+        return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull());
+    }
+    @Override
+    public NodeIterable<T> distinct() {
+        return new FilteredNodeIterable<>(this).distinct();
+    }
+    @Override
+    public T first() {
+        if (size() > 0) {
+            return get(0);
+        }
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorsIterable.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorsIterable.java	Sat Jun 16 02:20:02 2012 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.iterators.*;
 
-public abstract class NodeSuccessorsIterable extends NodeIterable<Node> {
+public abstract class NodeSuccessorsIterable extends AbstractNodeIterable<Node> {
     @Override
     public abstract NodeClassIterator iterator();
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsagesList.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsagesList.java	Sat Jun 16 02:20:02 2012 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.graph.iterators.*;
 
-public final class NodeUsagesList extends NodeIterable<Node> {
+public final class NodeUsagesList extends AbstractNodeIterable<Node> {
 
     protected static final Node[] EMPTY_NODE_ARRAY = new Node[0];
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph.iterators;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+
+public abstract class AbstractNodeIterable<T extends Node> implements NodeIterable<T> {
+    @Override
+    public NodeIterable<T> until(final T u) {
+        return new FilteredNodeIterable<>(this).until(u);
+    }
+    @Override
+    public NodeIterable<T> until(final Class<? extends T> clazz) {
+        return new FilteredNodeIterable<>(this).until(clazz);
+    }
+    @Override
+    @SuppressWarnings("unchecked")
+    public <F extends T> NodeIterable<F> filter(Class<F> clazz) {
+        return (NodeIterable<F>) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz));
+    }
+    @Override
+    public NodeIterable<T> filterInterface(Class<?> iface) {
+        return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface));
+    }
+    @Override
+    public FilteredNodeIterable<T> filter(NodePredicate predicate) {
+        return new FilteredNodeIterable<>(this).and(predicate);
+    }
+    @Override
+    public FilteredNodeIterable<T> nonNull() {
+        return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull());
+    }
+    @Override
+    public NodeIterable<T> distinct() {
+        return new FilteredNodeIterable<>(this).distinct();
+    }
+    @Override
+    public List<T> snapshot() {
+        ArrayList<T> list = new ArrayList<>();
+        for (T n : this) {
+            list.add(n);
+        }
+        return list;
+    }
+    @Override
+    public T first() {
+        Iterator<T> iterator = iterator();
+        if (iterator.hasNext()) {
+            return iterator.next();
+        }
+        return null;
+    }
+    @Override
+    public int count() {
+        int count = 0;
+        Iterator<T> iterator = iterator();
+        while (iterator.hasNext()) {
+            iterator.next();
+            count++;
+        }
+        return count;
+    }
+    @Override
+    public boolean isEmpty() {
+        return !iterator().hasNext();
+    }
+    @Override
+    public boolean isNotEmpty() {
+        return iterator().hasNext();
+    }
+    @Override
+    public boolean contains(T node) {
+        return this.filter(NodePredicates.equals(node)).isNotEmpty();
+    }
+}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java	Sat Jun 16 02:20:02 2012 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.graph.*;
 
-public class FilteredNodeIterable<T extends Node> extends NodeIterable<T> {
+public class FilteredNodeIterable<T extends Node> extends AbstractNodeIterable<T> {
     private final NodeIterable<T> nodeIterable;
     private NodePredicate predicate = NodePredicates.alwaysTrue();
     private NodePredicate until = NodePredicates.isNull();
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java	Sat Jun 16 02:20:02 2012 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,59 +26,32 @@
 
 import com.oracle.graal.graph.*;
 
-public abstract class NodeIterable<T extends Node> implements Iterable<T> {
-    public NodeIterable<T> until(final T u) {
-        return new FilteredNodeIterable<>(this).until(u);
-    }
-    public NodeIterable<T> until(final Class<? extends T> clazz) {
-        return new FilteredNodeIterable<>(this).until(clazz);
-    }
-    @SuppressWarnings("unchecked")
-    public <F extends T> NodeIterable<F> filter(Class<F> clazz) {
-        return (NodeIterable<F>) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz));
-    }
-    public NodeIterable<T> filterInterface(Class<?> iface) {
-        return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface));
-    }
-    public FilteredNodeIterable<T> filter(NodePredicate predicate) {
-        return new FilteredNodeIterable<>(this).and(predicate);
-    }
-    public FilteredNodeIterable<T> nonNull() {
-        return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull());
-    }
-    public NodeIterable<T> distinct() {
-        return new FilteredNodeIterable<>(this).distinct();
-    }
-    public List<T> snapshot() {
-        ArrayList<T> list = new ArrayList<>();
-        for (T n : this) {
-            list.add(n);
-        }
-        return list;
-    }
-    public T first() {
-        Iterator<T> iterator = iterator();
-        if (iterator.hasNext()) {
-            return iterator.next();
-        }
-        return null;
-    }
-    public int count() {
-        int count = 0;
-        Iterator<T> iterator = iterator();
-        while (iterator.hasNext()) {
-            iterator.next();
-            count++;
-        }
-        return count;
-    }
-    public boolean isEmpty() {
-        return !iterator().hasNext();
-    }
-    public boolean isNotEmpty() {
-        return iterator().hasNext();
-    }
-    public boolean contains(T node) {
-        return this.filter(NodePredicates.equals(node)).isNotEmpty();
-    }
+public interface NodeIterable<T extends Node> extends Iterable<T> {
+
+    NodeIterable<T> until(T u);
+
+    NodeIterable<T> until(Class< ? extends T> clazz);
+
+    <F extends T> NodeIterable<F> filter(Class<F> clazz);
+
+    NodeIterable<T> filterInterface(Class< ? > iface);
+
+    FilteredNodeIterable<T> filter(NodePredicate predicate);
+
+    FilteredNodeIterable<T> nonNull();
+
+    NodeIterable<T> distinct();
+
+    List<T> snapshot();
+
+    T first();
+
+    int count();
+
+    boolean isEmpty();
+
+    boolean isNotEmpty();
+
+    boolean contains(T node);
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Sat Jun 16 02:20:02 2012 +0200
@@ -43,6 +43,7 @@
     private final MethodFilter[] methodFilter;
     private final List<DebugDumpHandler> dumpHandlers = new ArrayList<>();
     private final PrintStream output;
+    private final Set<Object> extraFilters = new HashSet<>();
 
     public HotSpotDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter, PrintStream output) {
         this.logFilter = DebugFilter.parse(logFilter);
@@ -102,14 +103,18 @@
     }
 
     private boolean checkMethodFilter() {
-        if (methodFilter == null) {
+        if (methodFilter == null && extraFilters.isEmpty()) {
             return true;
         } else {
             for (Object o : Debug.context()) {
-                if (o instanceof JavaMethod) {
-                    for (MethodFilter filter : methodFilter) {
-                        if (filter.matches((JavaMethod) o)) {
-                            return true;
+                if (extraFilters.contains(o)) {
+                    return true;
+                } else if (methodFilter != null) {
+                    if (o instanceof JavaMethod) {
+                        for (MethodFilter filter : methodFilter) {
+                            if (filter.matches((JavaMethod) o)) {
+                                return true;
+                            }
                         }
                     }
                 }
@@ -176,4 +181,14 @@
     public Collection<? extends DebugDumpHandler> dumpHandlers() {
         return dumpHandlers;
     }
+
+    @Override
+    public void addToContext(Object o) {
+        extraFilters.add(o);
+    }
+
+    @Override
+    public void removeFromContext(Object o) {
+        extraFilters.remove(o);
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Sat Jun 16 02:20:02 2012 +0200
@@ -37,7 +37,7 @@
     // os information, register layout, code generation, ...
     public boolean windowsOs;
     public int codeEntryAlignment;
-    public boolean verifyPointers;
+    public boolean verifyOops;
     public boolean useFastLocking;
     public boolean useFastNewObjectArray;
     public boolean useFastNewTypeArray;
@@ -103,7 +103,7 @@
     public long monitorExitStub;
     public long fastMonitorEnterStub;
     public long fastMonitorExitStub;
-    public long verifyPointerStub;
+    public long verifyOopStub;
 
     public void check() {
         assert vmPageSize >= 16;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Sat Jun 16 02:20:02 2012 +0200
@@ -201,6 +201,11 @@
         return constantPool;
     }
 
+    /**
+     * Gets the instance size of this type. If an instance of this type cannot
+     * be fast path allocated, then the returned value is negative (its absolute
+     * value gives the size).
+     */
     public int instanceSize() {
         return instanceSize;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java	Sat Jun 16 02:20:02 2012 +0200
@@ -783,6 +783,7 @@
     public XirSnippet genNewInstance(XirSite site, JavaType type) {
         HotSpotResolvedJavaType resolvedType = (HotSpotResolvedJavaType) type;
         int instanceSize = resolvedType.instanceSize();
+        assert instanceSize >= 0;
         return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(resolvedType.klassOop()));
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.hotspot.target.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Node implementing a call to HotSpot's object pointer verification stub.
+ *
+ * @see AMD64VerifyOopStubCallOp
+ */
+public class VerifyOopStubCall extends FixedWithNextNode implements LIRGenLowerable {
+
+    @Input private final ValueNode object;
+
+    public VerifyOopStubCall(ValueNode object) {
+        super(StampFactory.objectNonNull());
+        this.object = object;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        LIRDebugInfo info = gen.state();
+        AMD64VerifyOopStubCallOp op = new AMD64VerifyOopStubCallOp(gen.operand(object), info);
+        gen.append(op);
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static Object call(Object object) {
+        throw new UnsupportedOperationException();
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java	Sat Jun 16 02:20:02 2012 +0200
@@ -70,9 +70,9 @@
             if (klassState != klassStateFullyInitialized()) {
                 if (logType != null) {
                     Log.print(logType);
-                    Log.println(" - uninitialized");
+                    Log.println(" - uninit alloc");
                 }
-                return NewInstanceStubCall.call(hub);
+                return verifyOop(NewInstanceStubCall.call(hub));
             }
         }
 
@@ -84,17 +84,28 @@
             if (newTop.cmp(BE, end)) {
                 Object instance = cast(top, Object.class);
                 store(thread, 0, threadTlabTopOffset(), newTop);
-                return formatInstance(hub, size, instance, logType);
-            } else {
+                formatInstance(hub, size, instance);
                 if (logType != null) {
                     Log.print(logType);
-                    Log.println(" - stub allocate");
+                    Log.print(" - fast alloc at ");
+                    Log.printlnAddress(instance);
                 }
-                return NewInstanceStubCall.call(hub);
+                return verifyOop(instance);
             }
-        } else {
-            return NewInstanceStubCall.call(hub);
+        }
+
+        if (logType != null) {
+            Log.print(logType);
+            Log.println(" - slow alloc");
         }
+        return verifyOop(NewInstanceStubCall.call(hub));
+    }
+
+    private static Object verifyOop(Object object) {
+        if (verifyOops()) {
+            VerifyOopStubCall.call(object);
+        }
+        return object;
     }
 
     private static Word asWord(Object object) {
@@ -108,7 +119,7 @@
     /**
      * Formats the header of a created instance and zeroes out its body.
      */
-    private static Object formatInstance(Object hub, int size, Object instance, String logType) {
+    private static void formatInstance(Object hub, int size, Object instance) {
         Word headerPrototype = cast(load(hub, 0, instanceHeaderPrototypeOffset(), wordKind()), Word.class);
         store(instance, 0, 0, headerPrototype);
         store(instance, 0, hubOffset(), hub);
@@ -116,13 +127,11 @@
         for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
             store(instance, 0, offset, 0);
         }
-        if (logType != null) {
-            Log.print("allocated instance of ");
-            Log.print(logType);
-            Log.print(" at ");
-            Log.printlnAddress(instance);
-        }
-        return instance;
+    }
+
+    @Fold
+    private static boolean verifyOops() {
+        return HotSpotGraalRuntime.getInstance().getConfig().verifyOops;
     }
 
     @Fold
@@ -192,11 +201,14 @@
             HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) newInstanceNode.instanceClass();
             HotSpotKlassOop hub = type.klassOop();
             int instanceSize = type.instanceSize();
+            assert (instanceSize % wordSize()) == 0;
+            assert instanceSize >= 0;
             Key key = new Key(newInstance).add("size", instanceSize).add("checkInit", !type.isInitialized()).add("useTLAB", useTLAB).add("logType", LOG_ALLOCATION ? type.name() : null);
             Arguments arguments = arguments("hub", hub);
             SnippetTemplate template = cache.get(key);
             Debug.log("Lowering newInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, arguments);
             //System.out.printf("Lowering newInstance in %s: node=%s, template=%s, arguments=%s%n", graph, newInstanceNode, template, arguments);
+            //DebugScope.getConfig().addToContext(graph.method());
             template.instantiate(runtime, newInstanceNode, newInstanceNode, arguments);
             new DeadCodeEliminationPhase().apply(graph);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.target;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+
+/**
+ * A call to HotSpot's object pointer verification stub.
+ */
+public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction {
+    public AMD64VerifyOopStubCallOp(Value object, LIRDebugInfo info) {
+        super("VERIFY_OOP", LIRInstruction.NO_OPERANDS, info, new Value[] {object}, NO_OPERANDS, NO_OPERANDS);
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        Register object = asRegister(input(0));
+        // r13: (in) object
+        if (object != AMD64.r13) {
+            masm.push(AMD64.r13);
+            masm.movl(AMD64.r13, object);
+        }
+        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, info);
+        if (object != AMD64.r13) {
+            masm.pop(AMD64.r13);
+        }
+    }
+
+    @Override
+    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+        if (mode == OperandMode.Input) {
+            return EnumSet.of(OperandFlag.Register);
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy02.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.jtt.optimize;
+
+import org.junit.*;
+
+/*
+ * Tests calls to the array copy method.
+ */
+public class ArrayCopy02 {
+
+    public static int[] src = new int[]{0, 1, 2, 3, 4, 5};
+    public static int[] dest0 = new int[]{5, 4, 3, 2, 1, 0};
+    public static int[] dest = new int[]{5, 4, 3, 2, 1, 0};
+
+    @Before
+    public void setUp() {
+        System.currentTimeMillis();
+        for (int i = 0; i < dest.length; i++) {
+            dest[i] = dest0[i];
+        }
+    }
+
+    public static int[] test(int srcPos, int destPos, int length) {
+        System.arraycopy(src, srcPos, dest, destPos, length);
+        return dest;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertArrayEquals(new int[] {5, 4, 3, 2, 1, 0}, test(0, 0, 0));
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run1() throws Throwable {
+        test(0, 0, -1);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run2() throws Throwable {
+        test(-1, 0, 0);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run3() throws Throwable {
+        test(0, -1, 0);
+    }
+
+    @Test
+    public void run4() throws Throwable {
+        Assert.assertArrayEquals(new int[] {0, 1, 3, 2, 1, 0}, test(0, 0, 2));
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run5() throws Throwable {
+        test(0, 1, 6);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run6() throws Throwable {
+        test(1, 0, 6);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run7() throws Throwable {
+        test(1, 1, -1);
+    }
+
+    @Test
+    public void run8() throws Throwable {
+        Assert.assertArrayEquals(new int[] {5, 0, 1, 2, 1, 0}, test(0, 1, 2));
+    }
+
+    @Test
+    public void run9() throws Throwable {
+        Assert.assertArrayEquals(new int[] {1, 2, 3, 2, 1, 0}, test(1, 0, 2));
+    }
+
+    @Test
+    public void run10() throws Throwable {
+        Assert.assertArrayEquals(new int[] {5, 1, 2, 2, 1, 0}, test(1, 1, 2));
+    }
+
+    @Test
+    public void run11() throws Throwable {
+        Assert.assertArrayEquals(new int[] {0, 1, 2, 3, 4, 5}, test(0, 0, 6));
+    }
+
+    @Test
+    public void run12() throws Throwable {
+        Assert.assertArrayEquals(new int[] {5, 0, 1, 2, 3, 4}, test(0, 1, 5));
+    }
+
+    @Test
+    public void run13() throws Throwable {
+        Assert.assertArrayEquals(new int[] {1, 2, 3, 4, 5, 0}, test(1, 0, 5));
+    }
+
+    @Test
+    public void run14() throws Throwable {
+        Assert.assertArrayEquals(new int[] {5, 1, 2, 3, 4, 5}, test(1, 1, 5));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy03.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.jtt.optimize;
+
+import org.junit.*;
+
+/*
+ * Tests calls to the array copy method.
+ */
+public class ArrayCopy03 {
+
+    public static byte[] src = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    public static byte[] dest0 = new byte[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+    public static byte[] dest = new byte[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+
+    @Before
+    public void setUp() {
+        System.currentTimeMillis();
+        for (int i = 0; i < dest.length; i++) {
+            dest[i] = dest0[i];
+        }
+    }
+
+    public static byte[] test(int srcPos, int destPos, int length) {
+        System.arraycopy(src, srcPos, dest, destPos, length);
+        return dest;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertArrayEquals(new byte[] {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, test(0, 0, 0));
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run1() throws Throwable {
+        test(0, 0, -1);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run2() throws Throwable {
+        test(-1, 0, 0);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run3() throws Throwable {
+        test(0, -1, 0);
+    }
+
+    @Test
+    public void run4() throws Throwable {
+        Assert.assertArrayEquals(new byte[] {0, 1, 8, 7, 6, 5, 4, 3, 2, 1, 0}, test(0, 0, 2));
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run5() throws Throwable {
+        test(0, 1, 11);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run6() throws Throwable {
+        test(1, 0, 11);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run7() throws Throwable {
+        test(1, 1, -1);
+    }
+
+    @Test
+    public void run8() throws Throwable {
+        Assert.assertArrayEquals(new byte[] {10, 0, 1, 7, 6, 5, 4, 3, 2, 1, 0}, test(0, 1, 2));
+    }
+
+    @Test
+    public void run9() throws Throwable {
+        Assert.assertArrayEquals(new byte[] {1, 2, 8, 7, 6, 5, 4, 3, 2, 1, 0}, test(1, 0, 2));
+    }
+
+    @Test
+    public void run10() throws Throwable {
+        Assert.assertArrayEquals(new byte[] {10, 1, 2, 7, 6, 5, 4, 3, 2, 1, 0}, test(1, 1, 2));
+    }
+
+    @Test
+    public void run11() throws Throwable {
+        Assert.assertArrayEquals(new byte[] {0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0}, test(0, 0, 6));
+    }
+
+    @Test
+    public void run12() throws Throwable {
+        Assert.assertArrayEquals(new byte[] {10, 0, 1, 2, 3, 4, 4, 3, 2, 1, 0}, test(0, 1, 5));
+    }
+
+    @Test
+    public void run13() throws Throwable {
+        Assert.assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0}, test(1, 0, 5));
+    }
+
+    @Test
+    public void run14() throws Throwable {
+        Assert.assertArrayEquals(new byte[] {10, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0}, test(1, 1, 5));
+    }
+
+    @Test
+    public void run15() throws Throwable {
+        Assert.assertArrayEquals(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 11));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ReassociateConstants.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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.optimize;
+
+import org.junit.*;
+
+
+public class ReassociateConstants {
+    public static int rnd = (int) (Math.random() * 100);
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertEquals(rnd + 3, 1 + (rnd + 2));
+        Assert.assertEquals(rnd + 3, (rnd + 2) + 1);
+        Assert.assertEquals(rnd + 3, 1 + (2 + rnd));
+        Assert.assertEquals(rnd + 3, (2 + rnd) + 1);
+
+        Assert.assertEquals(-1 - rnd, 1 - (rnd + 2));
+        Assert.assertEquals(rnd + 1, (rnd + 2) - 1);
+        Assert.assertEquals(-1 - rnd, 1 - (2 + rnd));
+        Assert.assertEquals(rnd + 1, (2 + rnd) - 1);
+
+        Assert.assertEquals(rnd - 1, 1 + (rnd - 2));
+        Assert.assertEquals(rnd - 1, (rnd - 2) + 1);
+        Assert.assertEquals(-rnd + 3, 1 + (2 - rnd));
+        Assert.assertEquals(-rnd + 3, (2 - rnd) + 1);
+
+        Assert.assertEquals(-rnd + 3, 1 - (rnd - 2));
+        Assert.assertEquals(rnd - 3, (rnd - 2) - 1);
+        Assert.assertEquals(rnd + -1, 1 - (2 - rnd));
+        Assert.assertEquals(-rnd + 1, (2 - rnd) - 1);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -143,7 +143,7 @@
     }
 
     public NodeIterable<FixedNode> getBlockNodes() {
-        return new NodeIterable<FixedNode>() {
+        return new AbstractNodeIterable<FixedNode>() {
             @Override
             public Iterator<FixedNode> iterator() {
                 return new BlockNodeIterator(BeginNode.this);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -155,4 +155,8 @@
     public void simplify(SimplifierTool tool) {
         // nothing yet
     }
+
+    public boolean isLoopExit(BeginNode begin) {
+        return begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -191,6 +191,19 @@
         return differentValue;
     }
 
+    public ValueNode singleBackValue() {
+        assert merge() instanceof LoopBeginNode;
+        ValueNode differentValue = null;
+        for (ValueNode n : values().subList(merge().forwardEndCount(), values().size())) {
+            if (differentValue == null) {
+                differentValue = n;
+            } else if (differentValue != n) {
+                return null;
+            }
+        }
+        return differentValue;
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         ValueNode singleValue = singleValue();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.type.GenericStamp.*;
 import com.oracle.graal.nodes.util.*;
@@ -89,6 +90,17 @@
         return this instanceof ConstantNode;
     }
 
+    private static final NodePredicate IS_CONSTANT = new NodePredicate() {
+        @Override
+        public boolean apply(Node n) {
+            return n instanceof ValueNode && ((ValueNode) n).isConstant();
+        }
+    };
+
+    public static NodePredicate isConstantPredicate() {
+        return IS_CONSTANT;
+    }
+
     /**
      * Checks whether this value represents the null constant.
      * @return {@code true} if this value represents the null constant
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -68,6 +68,7 @@
                     return ConstantNode.forLong(0, graph());
                 }
             }
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -23,6 +23,8 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -53,4 +55,135 @@
         this.x = x;
         this.y = y;
     }
+
+    public enum ReassociateMatch {
+        x,
+        y;
+
+        public ValueNode getValue(BinaryNode binary) {
+            switch(this) {
+                case x:
+                    return binary.x();
+                case y:
+                    return binary.y();
+                default: throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        public ValueNode getOtherValue(BinaryNode binary) {
+            switch(this) {
+                case x:
+                    return binary.y();
+                case y:
+                    return binary.x();
+                default: throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    public static boolean canTryReassociate(BinaryNode node) {
+        return node instanceof IntegerAddNode || node instanceof IntegerSubNode || node instanceof IntegerMulNode
+                        || node instanceof AndNode || node instanceof OrNode || node instanceof XorNode;
+    }
+
+    public static ReassociateMatch findReassociate(BinaryNode binary, NodePredicate criterion) {
+        boolean resultX = criterion.apply(binary.x());
+        boolean resultY = criterion.apply(binary.y());
+        if (resultX && !resultY) {
+            return ReassociateMatch.x;
+        }
+        if (!resultX && resultY) {
+            return ReassociateMatch.y;
+        }
+        return null;
+    }
+
+    /* In reassociate, complexity comes from the handling of IntegerSub (non commutative) which can be mixed with IntegerAdd.
+     * if first tries to find m1, m2 which match the criterion :
+     * (a o m2) o m1
+     * (m2 o a) o m1
+     * m1 o (a o m2)
+     * m1 o (m2 o a)
+     * It then produces 4 boolean for the -/+ case
+     *  invertA : should the final expression be like *-a (rather than a+*)
+     *  aSub : should the final expression be like a-* (rather than a+*)
+     *  invertM1 : should the final expression contain -m1
+     *  invertM2 : should the final expression contain -m2
+     */
+    /**
+     * Tries to re-associate values which satisfy the criterion.
+     * For example with a constantness criterion : (a + 2) + 1 => a + (1 + 2)<br>
+     * This method accepts only reassociable operations (see {@linkplain #canTryReassociate(BinaryNode)}) such as +, -, *, &, | and ^
+     */
+    public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion) {
+        assert canTryReassociate(node);
+        ReassociateMatch match1 = findReassociate(node, criterion);
+        if (match1 == null) {
+            return node;
+        }
+        ValueNode otherValue = match1.getOtherValue(node);
+        boolean addSub = false;
+        boolean subAdd = false;
+        if (otherValue.getClass() != node.getClass()) {
+            if (node instanceof IntegerAddNode && otherValue instanceof IntegerSubNode) {
+                addSub = true;
+            } else if (node instanceof IntegerSubNode && otherValue instanceof IntegerAddNode) {
+                subAdd = true;
+            } else {
+                return node;
+            }
+        }
+        BinaryNode other = (BinaryNode) otherValue;
+        ReassociateMatch match2 = findReassociate(other, criterion);
+        if (match2 == null) {
+            return node;
+        }
+        boolean invertA = false;
+        boolean aSub =  false;
+        boolean invertM1 = false;
+        boolean invertM2 = false;
+        if (addSub) {
+            invertM2 = match2 == ReassociateMatch.y;
+            invertA = !invertM2;
+        } else if (subAdd) {
+            invertA = invertM2 = match1 == ReassociateMatch.x;
+            invertM1 = !invertM2;
+        } else if (node instanceof IntegerSubNode && other instanceof IntegerSubNode) {
+            invertA = match1 == ReassociateMatch.x ^ match2 == ReassociateMatch.x;
+            aSub = match1 == ReassociateMatch.y && match2 == ReassociateMatch.y;
+            invertM1 = match1 == ReassociateMatch.y && match2 == ReassociateMatch.x;
+            invertM2 = match1 == ReassociateMatch.x && match2 == ReassociateMatch.x;
+        }
+        assert !(invertM1 && invertM2) && !(invertA && aSub);
+        ValueNode m1 = match1.getValue(node);
+        ValueNode m2 = match2.getValue(other);
+        ValueNode a = match2.getOtherValue(other);
+        if (node instanceof IntegerAddNode || node instanceof IntegerSubNode) {
+            BinaryNode associated;
+            if (invertM1) {
+                associated = IntegerArithmeticNode.sub(m2, m1);
+            } else if (invertM2) {
+                associated = IntegerArithmeticNode.sub(m1, m2);
+            } else {
+                associated = IntegerArithmeticNode.add(m1, m2);
+            }
+            if (invertA) {
+                return IntegerArithmeticNode.sub(associated, a);
+            }
+            if (aSub) {
+                return IntegerArithmeticNode.sub(a, associated);
+            }
+            return IntegerArithmeticNode.add(a, associated);
+        } else if (node instanceof IntegerMulNode) {
+            return IntegerArithmeticNode.mul(a, IntegerAddNode.mul(m1, m2));
+        } else if (node instanceof AndNode) {
+            return LogicNode.and(a, LogicNode.and(m1, m2));
+        } else if (node instanceof OrNode) {
+            return LogicNode.or(a, LogicNode.or(m1, m2));
+        } else if (node instanceof XorNode) {
+            return LogicNode.xor(a, LogicNode.xor(m1, m2));
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -48,33 +48,27 @@
                 return ConstantNode.forLong(x().asConstant().asLong() + y().asConstant().asLong(), graph());
             }
         } else if (y().isConstant()) {
-            if (kind() == Kind.Int) {
-                int c = y().asConstant().asInt();
-                if (c == 0) {
-                    return x();
-                }
-            } else {
-                assert kind() == Kind.Long;
-                long c = y().asConstant().asLong();
-                if (c == 0) {
-                    return x();
-                }
+            long c = y().asConstant().asLong();
+            if (c == 0) {
+                return x();
             }
             // canonicalize expressions like "(a + 1) + 2"
-            if (x() instanceof IntegerAddNode) {
-                IntegerAddNode other = (IntegerAddNode) x();
-                if (other.y().isConstant()) {
-                    ConstantNode sum;
-                    if (kind() == Kind.Int) {
-                        sum = ConstantNode.forInt(y().asConstant().asInt() + other.y().asConstant().asInt(), graph());
-                    } else {
-                        assert kind() == Kind.Long;
-                        sum = ConstantNode.forLong(y().asConstant().asLong() + other.y().asConstant().asLong(), graph());
-                    }
-                    return graph().unique(new IntegerAddNode(kind(), other.x(), sum));
+            BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            if (reassociated != this) {
+                return reassociated;
+            }
+            if (c < 0) {
+                if (kind() == Kind.Int) {
+                    return IntegerArithmeticNode.sub(x(), ConstantNode.forInt((int) -c, graph()));
+                } else {
+                    assert kind() == Kind.Long;
+                    return IntegerArithmeticNode.sub(x(), ConstantNode.forLong(-c, graph()));
                 }
             }
         }
+        if (x() instanceof NegateNode) {
+            return IntegerArithmeticNode.sub(y(), ((NegateNode) x()).x());
+        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -59,4 +59,30 @@
                 throw ValueNodeUtil.shouldNotReachHere();
         }
     }
+
+    public static IntegerSubNode sub(ValueNode v1, ValueNode v2) {
+        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        switch(v1.kind()) {
+            case Int:
+                return graph.unique(new IntegerSubNode(Kind.Int, v1, v2));
+            case Long:
+                return graph.unique(new IntegerSubNode(Kind.Long, v1, v2));
+            default:
+                throw ValueNodeUtil.shouldNotReachHere();
+        }
+    }
+
+    public static IntegerDivNode div(ValueNode v1, ValueNode v2) {
+        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        switch(v1.kind()) {
+            case Int:
+                return graph.unique(new IntegerDivNode(Kind.Int, v1, v2));
+            case Long:
+                return graph.unique(new IntegerDivNode(Kind.Long, v1, v2));
+            default:
+                throw ValueNodeUtil.shouldNotReachHere();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -59,19 +59,7 @@
                 return graph().unique(new LeftShiftNode(kind(), x(), ConstantNode.forInt(CodeUtil.log2(c), graph())));
             }
             // canonicalize expressions like "(a * 1) * 2"
-            if (x() instanceof IntegerMulNode) {
-                IntegerMulNode other = (IntegerMulNode) x();
-                if (other.y().isConstant()) {
-                    ConstantNode sum;
-                    if (kind() == Kind.Int) {
-                        sum = ConstantNode.forInt(y().asConstant().asInt() * other.y().asConstant().asInt(), graph());
-                    } else {
-                        assert kind() == Kind.Long;
-                        sum = ConstantNode.forLong(y().asConstant().asLong() * other.y().asConstant().asLong(), graph());
-                    }
-                    return graph().unique(new IntegerMulNode(kind(), other.x(), sum));
-                }
-            }
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -51,17 +51,24 @@
             if (c == 0) {
                 return x();
             }
-            if (kind() == Kind.Int) {
-                return graph().unique(new IntegerAddNode(kind(), x(), ConstantNode.forInt((int) -c, graph())));
-            } else {
-                assert kind() == Kind.Long;
-                return graph().unique(new IntegerAddNode(kind(), x(), ConstantNode.forLong(-c, graph())));
+            BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            if (reassociated != this) {
+                return reassociated;
+            }
+            if (c < 0) {
+                if (kind() == Kind.Int) {
+                    return IntegerArithmeticNode.add(x(), ConstantNode.forInt((int) -c, graph()));
+                } else {
+                    assert kind() == Kind.Long;
+                    return IntegerArithmeticNode.add(x(), ConstantNode.forLong(-c, graph()));
+                }
             }
         } else if (x().isConstant()) {
             long c = x().asConstant().asLong();
             if (c == 0) {
                 return graph().unique(new NegateNode(y()));
             }
+           return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -38,4 +39,43 @@
     public LogicNode(Kind kind, ValueNode x, ValueNode y) {
         super(kind, x, y);
     }
+
+    public static LogicNode and(ValueNode v1, ValueNode v2) {
+        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        switch(v1.kind()) {
+            case Int:
+                return graph.unique(new AndNode(Kind.Int, v1, v2));
+            case Long:
+                return graph.unique(new AndNode(Kind.Long, v1, v2));
+            default:
+                throw ValueNodeUtil.shouldNotReachHere();
+        }
+    }
+
+    public static LogicNode or(ValueNode v1, ValueNode v2) {
+        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        switch(v1.kind()) {
+            case Int:
+                return graph.unique(new OrNode(Kind.Int, v1, v2));
+            case Long:
+                return graph.unique(new OrNode(Kind.Long, v1, v2));
+            default:
+                throw ValueNodeUtil.shouldNotReachHere();
+        }
+    }
+
+    public static LogicNode xor(ValueNode v1, ValueNode v2) {
+        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        switch(v1.kind()) {
+            case Int:
+                return graph.unique(new XorNode(Kind.Int, v1, v2));
+            case Long:
+                return graph.unique(new XorNode(Kind.Long, v1, v2));
+            default:
+                throw ValueNodeUtil.shouldNotReachHere();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -38,12 +38,12 @@
     }
 
     /**
-     * Creates new NegateOp instance.
+     * Creates new NegateNode instance.
      *
      * @param x the instruction producing the value that is input to this instruction
      */
     public NegateNode(ValueNode x) {
-        super(StampFactory.forKind(x.kind()));
+        super(x.stamp() instanceof IntegerStamp ? StampFactory.negate((IntegerStamp) x.stamp()) : StampFactory.forKind(x.kind()));
         this.x = x;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -68,6 +68,7 @@
                     return x();
                 }
             }
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Sat Jun 16 02:20:02 2012 +0200
@@ -62,6 +62,7 @@
                     return x();
                 }
             }
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Sat Jun 16 02:20:02 2012 +0200
@@ -128,6 +128,14 @@
         }
     }
 
+    public static Stamp negate(IntegerStamp stamp) {
+        Kind kind = stamp.kind();
+        if (stamp.lowerBound() != kind.minValue()) {
+            return new IntegerStamp(kind, -stamp.upperBound(), -stamp.lowerBound());
+        }
+        return forKind(kind);
+    }
+
     public static Stamp object() {
         return objectStamp;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/util/NodeIterators.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/util/NodeIterators.java	Sat Jun 16 02:20:02 2012 +0200
@@ -30,7 +30,7 @@
 public class NodeIterators {
 
     public static NodeIterable<FixedNode> dominators(final FixedNode n) {
-        return new NodeIterable<FixedNode>() {
+        return new AbstractNodeIterable<FixedNode>() {
             @Override
             public Iterator<FixedNode> iterator() {
                 return new NodeIterator<FixedNode>(){
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewInstanceTest.java	Sat Jun 16 02:19:38 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewInstanceTest.java	Sat Jun 16 02:20:02 2012 +0200
@@ -36,12 +36,20 @@
         Assert.assertTrue(expected != null);
         Assert.assertTrue(actual != null);
         super.assertEquals(expected.getClass(), actual.getClass());
+        if (expected.getClass() != Object.class) {
+            try {
+                expected.getClass().getDeclaredMethod("equals", Object.class);
+                super.assertEquals(expected, actual);
+            } catch (Exception e) {
+            }
+        }
     }
 
     @Test
     public void test1() {
         test("newObject");
         test("newBigObject");
+        test("newSomeObject");
         test("newEmptyString");
         test("newString", "value");
         test("newHashMap", 31);
@@ -55,6 +63,10 @@
         return new BigObject();
     }
 
+    public static SomeObject newSomeObject() {
+        return new SomeObject();
+    }
+
     public static String newEmptyString() {
         return new String();
     }
@@ -67,6 +79,30 @@
         return new HashMap(initialCapacity);
     }
 
+    static class SomeObject {
+        String name = "o1";
+        HashMap<String, Object> map = new HashMap<>();
+
+
+        public SomeObject() {
+            map.put(name, this.getClass());
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof SomeObject) {
+                SomeObject so = (SomeObject) obj;
+                return so.name.equals(name) && so.map.equals(map);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+    }
+
     static class BigObject {
         Object f01;
         Object f02;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/ReassociateAndCanonicalTest.java	Sat Jun 16 02:20:02 2012 +0200
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.tests;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+public class ReassociateAndCanonicalTest extends GraalCompilerTest {
+    public static int rnd = (int) (Math.random() * 100);
+
+    @Test
+    public void test1() {
+        test("test1Snippet", "ref1Snippet");
+    }
+
+    public static int test1Snippet() {
+        return 1 + (rnd + 2);
+    }
+
+    public static int ref1Snippet() {
+        return rnd + 3;
+    }
+
+    @Test
+    public void test2() {
+        test("test2Snippet", "ref2Snippet");
+    }
+
+    public static int test2Snippet() {
+        return rnd + 3;
+    }
+
+    public static int ref2Snippet() {
+        return (rnd + 2) + 1;
+    }
+
+    @Test
+    public void test3() {
+        test("test3Snippet", "ref3Snippet");
+    }
+
+    public static int test3Snippet() {
+        return rnd + 3;
+    }
+
+    public static int ref3Snippet() {
+        return 1 + (2 + rnd);
+    }
+
+    @Test
+    public void test4() {
+        test("test4Snippet", "ref4Snippet");
+    }
+
+    public static int test4Snippet() {
+        return rnd + 3;
+    }
+
+    public static int ref4Snippet() {
+        return (2 + rnd) + 1;
+    }
+
+    @Test
+    public void test5() {
+        test("test5Snippet", "ref5Snippet");
+    }
+
+    public static int test5Snippet() {
+        return -1 - rnd;
+    }
+
+    public static int ref5Snippet() {
+        return 1 - (rnd + 2);
+    }
+
+    @Test
+    public void test6() {
+        test("test6Snippet", "ref6Snippet");
+    }
+
+    public static int test6Snippet() {
+        return rnd + 1;
+    }
+
+    public static int ref6Snippet() {
+        return (rnd + 2) - 1;
+    }
+
+    @Test
+    public void test7() {
+        test("test7Snippet", "ref7Snippet");
+    }
+
+    public static int test7Snippet() {
+        return -1 - rnd;
+    }
+
+    public static int ref7Snippet() {
+        return 1 - (2 + rnd);
+    }
+
+    @Test
+    public void test8() {
+        test("test8Snippet", "ref8Snippet");
+    }
+
+    public static int test8Snippet() {
+        return rnd + 1;
+    }
+
+    public static int ref8Snippet() {
+        return (2 + rnd) - 1;
+    }
+
+    @Test
+    public void test9() {
+        test("test9Snippet", "ref9Snippet");
+    }
+
+    public static int test9Snippet() {
+        return rnd - 1;
+    }
+
+    public static int ref9Snippet() {
+        return 1 + (rnd - 2);
+    }
+
+    @Test
+    public void test10() {
+        test("test10Snippet", "ref10Snippet");
+    }
+
+    public static int test10Snippet() {
+        return rnd - 1;
+    }
+
+    public static int ref10Snippet() {
+        return (rnd - 2) + 1;
+    }
+
+    @Test
+    public void test11() {
+        test("test11Snippet", "ref11Snippet");
+    }
+
+    public static int test11Snippet() {
+        return -rnd + 3;
+    }
+
+    public static int ref11Snippet() {
+        return 1 + (2 - rnd);
+    }
+
+    @Test
+    public void test12() {
+        test("test12Snippet", "ref12Snippet");
+    }
+
+    public static int test12Snippet() {
+        return -rnd + 3;
+    }
+
+    public static int ref12Snippet() {
+        return (2 - rnd) + 1;
+    }
+
+    @Test
+    public void test13() {
+        test("test13Snippet", "ref13Snippet");
+    }
+
+    public static int test13Snippet() {
+        return -rnd + 3;
+    }
+
+    public static int ref13Snippet() {
+        return 1 - (rnd - 2);
+    }
+
+    @Test
+    public void test14() {
+        test("test14Snippet", "ref14Snippet");
+    }
+
+    public static int test14Snippet() {
+        return rnd - 3;
+    }
+
+    public static int ref14Snippet() {
+        return (rnd - 2) - 1;
+    }
+
+    @Test
+    public void test15() {
+        test("test15Snippet", "ref15Snippet");
+    }
+
+    public static int test15Snippet() {
+        return rnd + -1;
+    }
+
+    public static int ref15Snippet() {
+        return 1 - (2 - rnd);
+    }
+
+    @Test
+    public void test16() {
+        test("test16Snippet", "ref16Snippet");
+    }
+
+    public static int test16Snippet() {
+        return -rnd + 1;
+    }
+
+    public static int ref16Snippet() {
+        return (2 - rnd) - 1;
+    }
+
+    private <T extends Node & Node.IterableNodeType> void test(String test, String ref) {
+        StructuredGraph testGraph = parse(test);
+        new CanonicalizerPhase(null, runtime(), null).apply(testGraph);
+        StructuredGraph refGraph = parse(ref);
+        new CanonicalizerPhase(null, runtime(), null).apply(refGraph);
+        assertEquals(testGraph, refGraph);
+    }
+}
--- a/hotspot/.cproject	Sat Jun 16 02:19:38 2012 +0200
+++ b/hotspot/.cproject	Sat Jun 16 02:20:02 2012 +0200
@@ -43,6 +43,7 @@
 									<listOptionValue builtIn="false" value="TARGET_OS_ARCH_linux_x86=1"/>
 									<listOptionValue builtIn="false" value="TARGET_ARCH_MODEL_x86_64=1"/>
 									<listOptionValue builtIn="false" value="GRAAL=1"/>
+									<listOptionValue builtIn="false" value="COMPILER2=1"/>
 								</option>
 								<option id="gnu.cpp.compiler.option.preprocessor.undef.2137486146" name="Undefined symbols (-U)" superClass="gnu.cpp.compiler.option.preprocessor.undef"/>
 								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.866181452" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
@@ -71,8 +72,13 @@
 							</tool>
 						</toolChain>
 					</folderInfo>
+					<fileInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.426128354" name="addnode.cpp" rcbsApplicability="disable" resourcePath="vm/opto/addnode.cpp" toolsToInvoke="cdt.managedbuild.tool.gnu.cpp.compiler.base.1342888057.211119144">
+						<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1342888057.211119144" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base.1342888057">
+							<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.202578082" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+						</tool>
+					</fileInfo>
 					<sourceEntries>
-						<entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp|vm/opto" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+						<entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
 					</sourceEntries>
 				</configuration>
 			</storageModule>
@@ -91,6 +97,7 @@
 		</configuration>
 	</storageModule>
 	<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
 	<storageModule moduleId="scannerConfiguration">
 		<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
 		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.388217325;cdt.managedbuild.tool.gnu.solaris.cpp.compiler.base.377383651;cdt.managedbuild.tool.gnu.cpp.compiler.input.103897085">
@@ -105,12 +112,11 @@
 		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.cpp.compiler.base.1342888057;cdt.managedbuild.tool.gnu.cpp.compiler.input.866181452">
 			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
 		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.c.compiler.base.1535888880;cdt.managedbuild.tool.gnu.c.compiler.input.906671119">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+		</scannerConfigBuildInfo>
 		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.solaris.c.compiler.base.351149667;cdt.managedbuild.tool.gnu.c.compiler.input.820447325">
 			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
 		</scannerConfigBuildInfo>
-		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.solaris.base.945602881;cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577;cdt.managedbuild.tool.gnu.c.compiler.base.1535888880;cdt.managedbuild.tool.gnu.c.compiler.input.906671119">
-			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
-		</scannerConfigBuildInfo>
 	</storageModule>
-	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
 </cproject>
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Sat Jun 16 02:19:38 2012 +0200
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Sat Jun 16 02:20:02 2012 +0200
@@ -1036,6 +1036,10 @@
 
           __ push(rdi);
           __ push(rbx);
+#ifdef GRAAL
+          __ push(rcx);
+          __ push(rsi);
+#endif
 
           if (id == fast_new_instance_init_check_id) {
             // make sure the klass is initialized
@@ -1074,6 +1078,10 @@
 
           __ initialize_object(obj, klass, obj_size, 0, t1, t2);
           __ verify_oop(obj);
+#ifdef GRAAL
+          __ pop(rsi);
+          __ pop(rcx);
+#endif
           __ pop(rbx);
           __ pop(rdi);
           __ ret(0);
@@ -1087,11 +1095,19 @@
 
           __ initialize_object(obj, klass, obj_size, 0, t1, t2);
           __ verify_oop(obj);
+#ifdef GRAAL
+          __ pop(rsi);
+          __ pop(rcx);
+#endif
           __ pop(rbx);
           __ pop(rdi);
           __ ret(0);
 
           __ bind(slow_path);
+#ifdef GRAAL
+          __ pop(rsi);
+          __ pop(rcx);
+#endif
           __ pop(rbx);
           __ pop(rdi);
         }
@@ -1939,8 +1955,8 @@
       break;
     }
 
-    case graal_verify_pointer_id: {
-      __ verify_oop(r13, "graal verify pointer");
+    case graal_verify_oop_id: {
+      __ verify_oop(r13, "graal verify oop");
       __ ret(0);
       break;
     }
--- a/src/share/vm/c1/c1_Runtime1.cpp	Sat Jun 16 02:19:38 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Sat Jun 16 02:20:02 2012 +0200
@@ -206,7 +206,7 @@
     case handle_exception_nofpu_id:  // Unused on sparc
 #endif
 #ifdef GRAAL
-    case graal_verify_pointer_id:
+    case graal_verify_oop_id:
     case graal_unwind_exception_call_id:
     case graal_slow_subtype_check_id:
     case graal_arithmetic_frem_id:
--- a/src/share/vm/c1/c1_Runtime1.hpp	Sat Jun 16 02:19:38 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.hpp	Sat Jun 16 02:20:02 2012 +0200
@@ -76,7 +76,7 @@
   stub(graal_arithmetic_drem)        \
   stub(graal_monitorenter)           \
   stub(graal_monitorexit)            \
-  stub(graal_verify_pointer)         \
+  stub(graal_verify_oop)         \
   stub(graal_set_deopt_info)         \
   stub(graal_create_null_pointer_exception) \
   stub(graal_create_out_of_bounds_exception) \
--- a/src/share/vm/graal/graalCompiler.cpp	Sat Jun 16 02:19:38 2012 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Sat Jun 16 02:20:02 2012 +0200
@@ -278,8 +278,12 @@
   if (klass->oop_is_javaArray()) {
     HotSpotResolvedJavaType::set_isArrayClass(obj, true);
   } else {
+    int size = instanceKlass::cast(klass())->size_helper() * HeapWordSize;
+    if (!instanceKlass::cast(klass())->can_be_fastpath_allocated()) {
+      size = -size;
+    }
     HotSpotResolvedJavaType::set_isArrayClass(obj, false);
-    HotSpotResolvedJavaType::set_instanceSize(obj, instanceKlass::cast(klass())->size_helper() * HeapWordSize);
+    HotSpotResolvedJavaType::set_instanceSize(obj, size);
     HotSpotResolvedJavaType::set_hasFinalizer(obj, klass->has_finalizer());
   }
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Sat Jun 16 02:19:38 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Sat Jun 16 02:20:02 2012 +0200
@@ -781,7 +781,7 @@
 #else
   set_boolean(env, config, "windowsOs", false);
 #endif
-  set_boolean(env, config, "verifyPointers", VerifyOops);
+  set_boolean(env, config, "verifyOops", VerifyOops);
   set_boolean(env, config, "useFastLocking", UseFastLocking);
   set_boolean(env, config, "useFastNewObjectArray", UseFastNewObjectArray);
   set_boolean(env, config, "useFastNewTypeArray", UseFastNewTypeArray);
@@ -816,10 +816,15 @@
   set_int(env, config, "bciProfileWidth", BciProfileWidth);
   set_int(env, config, "typeProfileWidth", TypeProfileWidth);
 
+  // We use the fast path stub so that we get TLAB refills whenever possible instead of
+  // unconditionally allocating directly from the heap (which the slow path does).
+  // The stub must also do initialization when the compiled check fails.
+  Runtime1::StubID newInstanceStub = Runtime1::fast_new_instance_init_check_id;
+
   set_long(env, config, "debugStub", VmIds::addStub((address)warning));
   set_long(env, config, "instanceofStub", VmIds::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
-  set_long(env, config, "verifyPointerStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_pointer_id)));
-  set_long(env, config, "newInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_instance_id)));
+  set_long(env, config, "verifyOopStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_oop_id)));
+  set_long(env, config, "newInstanceStub", VmIds::addStub(Runtime1::entry_for(newInstanceStub)));
   set_long(env, config, "newTypeArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_type_array_id)));
   set_long(env, config, "newObjectArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_object_array_id)));
   set_long(env, config, "newMultiArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_multi_array_id)));