changeset 9563:325b394bc535

Merge.
author Doug Simon <doug.simon@oracle.com>
date Sat, 04 May 2013 23:09:25 +0200
parents 99ef9bcb3f32 (current diff) 9e77e858b6eb (diff)
children a1ba00323cc2
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java
diffstat 23 files changed, 357 insertions(+), 143 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Sat May 04 23:09:25 2013 +0200
@@ -26,7 +26,7 @@
 
 import junit.framework.Assert;
 
-import org.junit.*;
+import org.junit.Test;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
@@ -91,6 +91,22 @@
         compileSnippet("test4Snippet", 2, 2);
     }
 
+    public static long test5Snippet(A1 a1) {
+        long sum = 0;
+        A2 a2 = (A2) a1;
+        A3 a3 = (A3) a2;
+        sum += a2.x2;
+        return sum + a3.x3;
+    }
+
+    @Test
+    public void test5() {
+        StructuredGraph graph = compileSnippet("test5Snippet", 2, 1);
+        for (LoadFieldNode lfn : graph.getNodes().filter(LoadFieldNode.class)) {
+            Assert.assertTrue(lfn.object() instanceof CheckCastNode);
+        }
+    }
+
     private StructuredGraph compileSnippet(final String snippet, final int checkcasts, final int afterCanon) {
         return Debug.scope(snippet, new Callable<StructuredGraph>() {
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Sat May 04 23:09:25 2013 +0200
@@ -31,9 +31,9 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -66,17 +66,24 @@
             public void run() {
                 StructuredGraph graph = compileTestSnippet(snippet);
 
+                int counter = 0;
                 for (ReadNode rn : graph.getNodes().filter(ReadNode.class)) {
-                    LocationIdentity locId = rn.location().getLocationIdentity();
-                    if (locId instanceof ResolvedJavaField) {
-                        ResolvedJavaField field = (ResolvedJavaField) locId;
-                        if (field.getName().equals("x")) {
-                            Assert.assertTrue(rn.object() instanceof LocalNode);
-                        } else {
-                            Assert.assertTrue(rn.object() instanceof UnsafeCastNode);
+                    if (rn.location() instanceof ConstantLocationNode && rn.object().stamp() instanceof ObjectStamp) {
+                        long disp = ((ConstantLocationNode) rn.location()).getDisplacement();
+                        ResolvedJavaType receiverType = rn.object().objectStamp().type();
+                        ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(disp);
+
+                        if (field != null) {
+                            if (field.getName().equals("x")) {
+                                Assert.assertTrue(rn.object() instanceof LocalNode);
+                            } else {
+                                Assert.assertTrue(rn.object() instanceof UnsafeCastNode);
+                            }
+                            counter++;
                         }
                     }
                 }
+                Assert.assertEquals(2, counter);
 
                 Assert.assertTrue(graph.getNodes().filter(IsNullNode.class).count() == 1);
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Sat May 04 23:09:25 2013 +0200
@@ -90,6 +90,8 @@
  */
 public abstract class HotSpotRuntime implements GraalCodeCacheProvider, DisassemblerProvider, BytecodeDisassemblerProvider {
 
+    public static final Descriptor OSR_MIGRATION_END = new Descriptor("OSR_migration_end", true, void.class, long.class);
+
     public final HotSpotVMConfig config;
 
     protected final RegisterConfig regConfig;
@@ -868,6 +870,30 @@
             graph.removeFixed(commit);
         } else if (n instanceof CheckCastNode) {
             checkcastSnippets.lower((CheckCastNode) n, tool);
+        } else if (n instanceof OSRStartNode) {
+            OSRStartNode osrStart = (OSRStartNode) n;
+            StartNode newStart = graph.add(new StartNode());
+            LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind())));
+            RuntimeCallNode migrationEnd = graph.add(new RuntimeCallNode(OSR_MIGRATION_END, buffer));
+            migrationEnd.setStateAfter(osrStart.stateAfter());
+
+            newStart.setNext(migrationEnd);
+            FixedNode next = osrStart.next();
+            osrStart.setNext(null);
+            migrationEnd.setNext(next);
+            graph.setStart(newStart);
+
+            // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block)
+            int localsOffset = (graph.method().getMaxLocals() - 1) * 8;
+            for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) {
+                int size = FrameStateBuilder.stackSlots(osrLocal.kind());
+                int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
+                UnsafeLoadNode load = graph.add(new UnsafeLoadNode(buffer, offset, ConstantNode.forInt(0, graph), osrLocal.kind()));
+                osrLocal.replaceAndDelete(load);
+                graph.addBeforeFixed(migrationEnd, load);
+            }
+            osrStart.replaceAtUsages(newStart);
+            osrStart.safeDelete();
         } else if (n instanceof CheckCastDynamicNode) {
             checkcastSnippets.lower((CheckCastDynamicNode) n);
         } else if (n instanceof InstanceOfNode) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Sat May 04 23:09:25 2013 +0200
@@ -22,20 +22,14 @@
  */
 package com.oracle.graal.hotspot.phases;
 
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.RuntimeCallTarget.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.*;
+import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.java.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
@@ -43,29 +37,6 @@
 
 public class OnStackReplacementPhase extends Phase {
 
-    public static final Descriptor OSR_MIGRATION_END = new Descriptor("OSR_migration_end", true, void.class, long.class);
-
-    public class OSREntryProxyNode extends FloatingNode implements LIRLowerable {
-
-        @Input private ValueNode object;
-        @Input(notDataflow = true) private final RuntimeCallNode anchor;
-
-        public OSREntryProxyNode(ValueNode object, RuntimeCallNode anchor) {
-            super(object.stamp());
-            this.object = object;
-            this.anchor = anchor;
-        }
-
-        public RuntimeCallNode getAnchor() {
-            return anchor;
-        }
-
-        @Override
-        public void generate(LIRGeneratorTool generator) {
-            generator.setResult(this, generator.operand(object));
-        }
-    }
-
     @Override
     protected void run(StructuredGraph graph) {
         if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) {
@@ -114,39 +85,29 @@
             Debug.dump(graph, "OnStackReplacement loop peeling result");
         } while (true);
 
-        LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind())));
-        RuntimeCallNode migrationEnd = graph.add(new RuntimeCallNode(OSR_MIGRATION_END, buffer));
         FrameState osrState = osr.stateAfter();
-        migrationEnd.setStateAfter(osrState);
         osr.setStateAfter(null);
-
+        OSRStartNode osrStart = graph.add(new OSRStartNode());
         StartNode start = graph.start();
-        FixedNode rest = start.next();
-        start.setNext(migrationEnd);
         FixedNode next = osr.next();
         osr.setNext(null);
-        migrationEnd.setNext(next);
+        osrStart.setNext(next);
+        graph.setStart(osrStart);
+        osrStart.setStateAfter(osrState);
 
-        FrameState oldStartState = start.stateAfter();
-        start.setStateAfter(null);
-        GraphUtil.killWithUnusedFloatingInputs(oldStartState);
-
-        // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block)
-        int localsOffset = (graph.method().getMaxLocals() - 1) * 8;
         for (int i = 0; i < osrState.localsSize(); i++) {
             ValueNode value = osrState.localAt(i);
             if (value != null) {
                 ProxyNode proxy = (ProxyNode) value;
-                int size = FrameStateBuilder.stackSlots(value.kind());
-                int offset = localsOffset - (i + size - 1) * 8;
-                UnsafeLoadNode load = graph.add(new UnsafeLoadNode(buffer, offset, ConstantNode.forInt(0, graph), value.kind()));
-                OSREntryProxyNode newProxy = graph.add(new OSREntryProxyNode(load, migrationEnd));
-                proxy.replaceAndDelete(newProxy);
-                graph.addBeforeFixed(migrationEnd, load);
+                /*
+                 * we need to drop the stamp and go back to the kind since the types we see during
+                 * OSR may be too precise (if a branch was not parsed for example).
+                 */
+                proxy.replaceAndDelete(graph.unique(new OSRLocalNode(i, StampFactory.forKind(proxy.kind()))));
             }
         }
 
-        GraphUtil.killCFG(rest);
+        GraphUtil.killCFG(start);
 
         Debug.dump(graph, "OnStackReplacement result");
         new DeadCodeEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Sat May 04 23:09:25 2013 +0200
@@ -101,7 +101,7 @@
             if (memory.notEqual(0)) {
                 log(log, "newArray: allocated new array at %p\n", memory);
                 formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord()), true);
-                return verifyOop(memory.toObject());
+                return memory.toObject();
             }
         }
         log(log, "newArray: calling new_array_c\n", 0L);
@@ -113,7 +113,7 @@
             getAndClearObjectResult(thread());
             DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint);
         }
-        return verifyOop(getAndClearObjectResult(thread()));
+        return getAndClearObjectResult(thread());
     }
 
     public static final Descriptor NEW_ARRAY_C = descriptorFor(NewArrayStub.class, "newArrayC", false);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Sat May 04 23:09:25 2013 +0200
@@ -94,7 +94,7 @@
                     for (int offset = 2 * wordSize(); offset < sizeInBytes; offset += wordSize()) {
                         memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                     }
-                    return verifyOop(memory.toObject());
+                    return memory.toObject();
                 }
             }
         }
@@ -108,7 +108,7 @@
             getAndClearObjectResult(thread());
             DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint);
         }
-        return verifyOop(getAndClearObjectResult(thread()));
+        return getAndClearObjectResult(thread());
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewMultiArrayStub.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewMultiArrayStub.java	Sat May 04 23:09:25 2013 +0200
@@ -48,7 +48,7 @@
     private static Object newMultiArray(Word hub, int rank, Word dims) {
         newMultiArrayC(NEW_MULTI_ARRAY_C, thread(), hub, rank, dims);
         handlePendingException(true);
-        return verifyOop(getAndClearObjectResult(thread()));
+        return getAndClearObjectResult(thread());
     }
 
     public static final Descriptor NEW_MULTI_ARRAY_C = descriptorFor(NewMultiArrayStub.class, "newMultiArrayC", false);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Sat May 04 23:09:25 2013 +0200
@@ -679,7 +679,7 @@
     }
 
     private void genGoto() {
-        appendGoto(createTarget(1, currentBlock.successors.get(0), frameState));
+        appendGoto(createTarget(currentBlock.successors.get(0), frameState));
         assert currentBlock.numNormalSuccessors() == 1;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java	Sat May 04 23:09:25 2013 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.type.*;
+
+public abstract class AbstractLocalNode extends FloatingNode {
+
+    private final int index;
+
+    public AbstractLocalNode(int index, Stamp stamp) {
+        super(stamp);
+        this.index = index;
+    }
+
+    /**
+     * Gets the index of this local in the array of parameters. This is NOT the JVM local index.
+     * 
+     * @return the index
+     */
+    public int index() {
+        return index;
+    }
+
+    @Override
+    public String toString(Verbosity verbosity) {
+        if (verbosity == Verbosity.Name) {
+            return super.toString(Verbosity.Name) + "(" + index + ")";
+        } else {
+            return super.toString(verbosity);
+        }
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java	Sat May 04 23:09:25 2013 +0200
@@ -23,37 +23,15 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code Local} instruction is a placeholder for an incoming argument to a function call.
  */
 @NodeInfo(nameTemplate = "Local({p#index})")
-public final class LocalNode extends FloatingNode implements Node.IterableNodeType {
-
-    private final int index;
+public final class LocalNode extends AbstractLocalNode implements Node.IterableNodeType {
 
     public LocalNode(int index, Stamp stamp) {
-        super(stamp);
-        this.index = index;
-    }
-
-    /**
-     * Gets the index of this local in the array of parameters. This is NOT the JVM local index.
-     * 
-     * @return the index
-     */
-    public int index() {
-        return index;
-    }
-
-    @Override
-    public String toString(Verbosity verbosity) {
-        if (verbosity == Verbosity.Name) {
-            return super.toString(Verbosity.Name) + "(" + index + ")";
-        } else {
-            return super.toString(verbosity);
-        }
+        super(index, stamp);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Sat May 04 23:09:25 2013 +0200
@@ -44,20 +44,22 @@
 
     private final Set<Long> leafGraphIds = new HashSet<>(4);
 
-    private final StartNode start;
+    private StartNode start;
     private final ResolvedJavaMethod method;
     private final long graphId;
     private final int entryBCI;
 
     /**
-     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() start} node.
+     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start()
+     * start} node.
      */
     public StructuredGraph() {
         this(null, null);
     }
 
     /**
-     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() start} node.
+     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start()
+     * start} node.
      */
     public StructuredGraph(String name, ResolvedJavaMethod method) {
         this(name, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI);
@@ -73,7 +75,7 @@
 
     private StructuredGraph(String name, ResolvedJavaMethod method, long graphId, int entryBCI) {
         super(name);
-        this.start = add(new StartNode());
+        this.setStart(add(new StartNode()));
         this.method = method;
         this.graphId = graphId;
         this.entryBCI = entryBCI;
@@ -116,6 +118,10 @@
         return graphId;
     }
 
+    public void setStart(StartNode start) {
+        this.start = start;
+    }
+
     /**
      * @return the {@link Set} that contains the {@link #graphId()} of all graphs that were
      *         incorporated into this one (e.g. by inlining).
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Sat May 04 23:09:25 2013 +0200
@@ -41,7 +41,7 @@
         I2B(Int, Byte, false),
         I2C(Int, Char, false),
         I2S(Int, Short, false),
-        F2D(Float, Double, false),
+        F2D(Float, Double, true),
         D2F(Double, Float, false),
         I2F(Int, Float, false),
         I2D(Int, Double, true),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java	Sat May 04 23:09:25 2013 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.extended;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+@NodeInfo(nameTemplate = "OSRLocal({p#index})")
+public class OSRLocalNode extends AbstractLocalNode implements Node.IterableNodeType {
+
+    public OSRLocalNode(int index, Stamp stamp) {
+        super(index, stamp);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java	Sat May 04 23:09:25 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.extended;
+
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+public class OSRStartNode extends StartNode implements Lowerable {
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        if (loweringType == LoweringType.AFTER_GUARDS) {
+            tool.getRuntime().lower(this, tool);
+        }
+    }
+
+    public NodeIterable<OSRLocalNode> getOSRLocals() {
+        return usages().filter(OSRLocalNode.class);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Sat May 04 23:09:25 2013 +0200
@@ -102,19 +102,27 @@
 
     @Override
     public boolean push(PiNode parent) {
-        LocationIdentity locId = location().getLocationIdentity();
-        if (locId instanceof ResolvedJavaField) {
-            ResolvedJavaType fieldType = ((ResolvedJavaField) locId).getDeclaringClass();
-            ValueNode piValueStamp = parent.object();
-            ResolvedJavaType beforePiType = piValueStamp.objectStamp().type();
+        if (location() instanceof ConstantLocationNode) {
+            long displacement = ((ConstantLocationNode) location()).getDisplacement();
+            if (parent.stamp() instanceof ObjectStamp) {
+                ObjectStamp piStamp = parent.objectStamp();
+                ResolvedJavaType receiverType = piStamp.type();
+                if (receiverType != null) {
+                    ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement);
 
-            if (beforePiType != null && fieldType.isAssignableFrom(beforePiType)) {
-                ObjectStamp piStamp = parent.objectStamp();
-                if (piStamp.nonNull() == piValueStamp.objectStamp().nonNull() && piStamp.alwaysNull() == piValueStamp.objectStamp().alwaysNull()) {
-                    replaceFirstInput(parent, piValueStamp);
-                    return true;
+                    if (field != null) {
+                        ResolvedJavaType declaringClass = field.getDeclaringClass();
+                        if (declaringClass.isAssignableFrom(receiverType) && declaringClass != receiverType) {
+                            ObjectStamp piValueStamp = parent.object().objectStamp();
+                            if (piStamp.nonNull() == piValueStamp.nonNull() && piStamp.alwaysNull() == piValueStamp.alwaysNull()) {
+                                replaceFirstInput(parent, parent.object());
+                                return true;
+                            }
+                        }
+                    }
                 }
             }
+
         }
         return false;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Sat May 04 23:09:25 2013 +0200
@@ -98,8 +98,8 @@
     }
 
     @NodeIntrinsic
-    public static native Location constantLocation(Object identity, Kind kind, long displacement);
+    public static native Location constantLocation(LocationIdentity identity, Kind kind, long displacement);
 
     @NodeIntrinsic
-    public static native Location indexedLocation(Object identity, Kind kind, long displacement, int index, int indexScaling);
+    public static native Location indexedLocation(LocationIdentity identity, Kind kind, long displacement, int index, int indexScaling);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Sat May 04 23:09:25 2013 +0200
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.LocationNode.Location;
 import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -91,7 +92,7 @@
     }
 
     @NodeIntrinsic
-    public static native void writeMemory(Object object, Object value, Object location, @ConstantNodeParameter WriteBarrierType barrierType);
+    public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter WriteBarrierType barrierType);
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Sat May 04 23:09:25 2013 +0200
@@ -85,11 +85,15 @@
             // checkcast.
             return object();
         }
+
         // remove checkcast if next node is a more specific checkcast
-        if (next() instanceof CheckCastNode) {
-            CheckCastNode ccn = (CheckCastNode) next();
-            if (ccn != null && ccn.type() != null && this == ccn.object() && type.isAssignableFrom(ccn.type())) {
-                return object();
+        if (predecessor() instanceof CheckCastNode) {
+            CheckCastNode ccn = (CheckCastNode) predecessor();
+            if (ccn != null && ccn.type != null && ccn == object && ccn.forStoreCheck == forStoreCheck && ccn.type.isAssignableFrom(type)) {
+                StructuredGraph graph = (StructuredGraph) ccn.graph();
+                CheckCastNode newccn = graph.add(new CheckCastNode(type, ccn.object, ccn.profile, ccn.forStoreCheck));
+                graph.replaceFixedWithFixed(ccn, newccn);
+                return newccn;
             }
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Sat May 04 23:09:25 2013 +0200
@@ -35,7 +35,7 @@
 
     @Input private final NodeInputList<VirtualObjectNode> virtualObjects = new NodeInputList<>(this);
     @Input private final NodeInputList<ValueNode> values = new NodeInputList<>(this);
-    private final List<int[]> locks = new ArrayList<>();
+    private List<int[]> locks = new ArrayList<>();
 
     public CommitAllocationNode() {
         super(StampFactory.forVoid());
@@ -72,6 +72,13 @@
     }
 
     @Override
+    public Node clone(Graph into) {
+        CommitAllocationNode clone = (CommitAllocationNode) super.clone(into);
+        clone.locks = new ArrayList<>(locks);
+        return clone;
+    }
+
+    @Override
     public void virtualize(VirtualizerTool tool) {
         int pos = 0;
         for (int i = 0; i < virtualObjects.size(); i++) {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Sat May 04 23:09:25 2013 +0200
@@ -34,7 +34,10 @@
     private static final boolean ____ = false;
     // Checkstyle: resume
 
-    public static int     Threads                            = 4;
+    public static int     Threads;
+    static {
+        Threads = Runtime.getRuntime().availableProcessors();
+    }
 
     public static String  CompilerConfiguration              = "basic";
     public static String  GraalRuntime                       = "basic";
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Sat May 04 23:09:25 2013 +0200
@@ -334,7 +334,7 @@
         // default handler
         createElementForNode(node);
 
-        List<Object> children = NodeUtil.findNodeChildren(node);
+        List<Node> children = NodeUtil.findNodeChildren((Node) node);
         for (Object child : children) {
             if (child == null) {
                 continue;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Sat May 04 23:09:25 2013 +0200
@@ -29,6 +29,9 @@
 
 import sun.misc.*;
 
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.api.nodes.Node.Children;
+
 /**
  * Utility class that manages the special access methods for node instances.
  */
@@ -73,15 +76,13 @@
                 }
 
                 // Node fields
-                if (Node.class.isAssignableFrom(field.getType())) {
-                    if (!field.getName().equals("parent")) {
-                        nodeFieldOffsetsList.add(unsafe.objectFieldOffset(field));
-                        nodeFieldClassesList.add(field.getType());
-                    } else {
-                        parentOffsetTemp = unsafe.objectFieldOffset(field);
-                        parentClassTmp = field.getType();
-                    }
-                } else if (field.getType().getComponentType() != null && Node.class.isAssignableFrom(field.getType().getComponentType())) {
+                if (Node.class.isAssignableFrom(field.getType()) && field.getName().equals("parent")) {
+                    parentOffsetTemp = unsafe.objectFieldOffset(field);
+                    parentClassTmp = field.getType();
+                } else if (Node.class.isAssignableFrom(field.getType()) && field.getAnnotation(Child.class) != null) {
+                    nodeFieldOffsetsList.add(unsafe.objectFieldOffset(field));
+                    nodeFieldClassesList.add(field.getType());
+                } else if (field.getType().getComponentType() != null && Node.class.isAssignableFrom(field.getType().getComponentType()) && field.getAnnotation(Children.class) != null) {
                     nodeArrayFieldOffsetsList.add(unsafe.objectFieldOffset(field));
                     nodeArrayFieldClassesList.add(field.getType());
                 } else {
@@ -251,18 +252,18 @@
         return (T) clone;
     }
 
-    public static List<Object> findNodeChildren(Object node) {
-        List<Object> nodes = new ArrayList<>();
+    public static List<Node> findNodeChildren(Node node) {
+        List<Node> nodes = new ArrayList<>();
         NodeClass nodeClass = NodeClass.get(node.getClass());
 
         for (long fieldOffset : nodeClass.nodeFieldOffsets) {
             Object child = unsafe.getObject(node, fieldOffset);
             if (child != null) {
-                nodes.add(child);
+                nodes.add((Node) child);
             }
         }
         for (long fieldOffset : nodeClass.nodeArrayFieldOffsets) {
-            Object[] children = (Object[]) unsafe.getObject(node, fieldOffset);
+            Node[] children = (Node[]) unsafe.getObject(node, fieldOffset);
             if (children != null) {
                 nodes.addAll(Arrays.asList(children));
             }
@@ -386,10 +387,8 @@
     }
 
     @SuppressWarnings("unchecked")
-    public static <T> T findFirstNodeInstance(Object root, Class<T> clazz) {
-        List<Object> childNodes = findNodeChildren(root);
-
-        for (Object childNode : childNodes) {
+    public static <T> T findFirstNodeInstance(Node root, Class<T> clazz) {
+        for (Node childNode : findNodeChildren(root)) {
             if (clazz.isInstance(childNode)) {
                 return (T) childNode;
             } else {
@@ -474,8 +473,16 @@
     }
 
     public static String printTreeToString(Node node) {
+        return printTreeToString(node, false);
+    }
+
+    private static String printTreeToString(Node node, boolean compact) {
         ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
-        printTree(new PrintStream(byteOut), node);
+        if (compact) {
+            printCompactTree(new PrintStream(byteOut), node);
+        } else {
+            printTree(new PrintStream(byteOut), node);
+        }
         try {
             byteOut.flush();
         } catch (IOException e) {
@@ -494,6 +501,61 @@
         printTree(p, node, new NodeTreeResolver());
     }
 
+    public static String printCompactTreeToString(Node node) {
+        return printTreeToString(node, true);
+    }
+
+    public static void printCompactTree(PrintStream p, Node node) {
+        printCompactTree(p, null, node, 1);
+    }
+
+    private static void printCompactTree(PrintStream p, Node parent, Node node, int level) {
+        if (node == null) {
+            return;
+        }
+        for (int i = 0; i < level; i++) {
+            p.print("  ");
+        }
+        if (parent == null) {
+            p.println(node.getClass().getSimpleName());
+        } else {
+            String fieldName = null;
+            Field[] fields = NodeUtil.getAllFields(parent.getClass());
+            try {
+                for (Field field : fields) {
+                    field.setAccessible(true);
+                    Object value = field.get(parent);
+                    if (value == node) {
+                        fieldName = field.getName();
+                        break;
+                    } else if (value instanceof Node[]) {
+                        int index = 0;
+                        for (Node arrayNode : (Node[]) value) {
+                            if (arrayNode == node) {
+                                fieldName = field.getName() + "[" + index + "]";
+                                break;
+                            }
+                            index++;
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+            if (fieldName == null) {
+                fieldName = "unknownField";
+            }
+            p.print(fieldName);
+            p.print(" = ");
+            p.println(node.getClass().getSimpleName());
+        }
+
+        for (Node child : node.getChildren()) {
+            printCompactTree(p, node, child, level + 1);
+        }
+    }
+
     /**
      * Prints a human readable form of a tree to the given {@link PrintStream}. The
      * {@link TreeResolver} interface needs to be implemented to specify how the method can read the
@@ -639,12 +701,12 @@
 
         @Override
         public boolean isChildObject(Field f) {
-            return Node.class.isAssignableFrom(f.getType());
+            return Node.class.isAssignableFrom(f.getType()) && f.getAnnotation(Child.class) != null;
         }
 
         @Override
         public boolean isChildArrayObject(Field f) {
-            return f.getType().getComponentType() != null && Node.class.isAssignableFrom(f.getType().getComponentType());
+            return f.getType().getComponentType() != null && Node.class.isAssignableFrom(f.getType().getComponentType()) && f.getAnnotation(Children.class) != null;
         }
 
         @Override
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Sat May 04 23:05:46 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Sat May 04 23:09:25 2013 +0200
@@ -1460,8 +1460,7 @@
 
             List<ActualParameter> executeParameters = new ArrayList<>();
             for (ActualParameter sourceParameter : executable.getParameters()) {
-                NodeChildData field = specialization.getNode().findChild(sourceParameter.getSpecification().getName());
-                if (field == null) {
+                if (!sourceParameter.getSpecification().isSignature()) {
                     continue;
                 }
 
@@ -1645,21 +1644,24 @@
 
             for (ActualParameter targetParameter : targetParameters) {
                 NodeChildData field = sourceNode.findChild(targetParameter.getSpecification().getName());
-                if (field == null) {
+                if (!targetParameter.getSpecification().isSignature()) {
                     continue;
                 }
+
                 TypeData targetType = targetParameter.getTypeSystemType();
-
-                ExecutableTypeData targetExecutable = field.findExecutableType(getContext(), targetType);
+                ExecutableTypeData targetExecutable = null;
+                if (field != null) {
+                    targetExecutable = field.findExecutableType(getContext(), targetType);
+                }
 
                 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName());
 
                 String targetVariableName = valueName(targetParameter);
                 CodeTree executionExpression = null;
-                if (cast || sourceParameter != null) {
+                if ((sourceParameter != null && cast) || sourceParameter != null) {
                     TypeData sourceType = sourceParameter.getTypeSystemType();
-                    if (!sourceType.needsCastTo(getContext(), targetType)) {
-                        if (field.isShortCircuit() && sourceParameter != null) {
+                    if (targetExecutable == null || !sourceType.needsCastTo(getContext(), targetType)) {
+                        if (field != null && field.isShortCircuit() && sourceParameter != null) {
                             builder.tree(createShortCircuitValue(builder, specialization, field, targetParameter.getPreviousParameter(), unexpectedParameter));
                         }
                         builder.startStatement();
@@ -1667,8 +1669,10 @@
                         builder.string(valueName(targetParameter)).string(" = ");
                         builder.tree(CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)));
                         builder.end();
+                        continue;
                     } else {
-                        executionExpression = createExpectExecutableType(sourceNode, sourceType, targetExecutable, CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)));
+                        CodeTree valueTree = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
+                        executionExpression = createExpectExecutableType(sourceNode, sourceType, targetExecutable, valueTree);
                     }
                 } else if (sourceParameter == null) {
                     executionExpression = createExecuteChildExpression(builder, field, targetParameter, unexpectedParameter);