changeset 5628:65bf69eb147c

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Thu, 14 Jun 2012 18:03:43 +0200
parents e1b29c516354 (current diff) f8eb2cb76a2f (diff)
children 26a060cc58ca
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/SnippetIntrinsificationPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java
diffstat 73 files changed, 1516 insertions(+), 1200 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCall.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCall.java	Thu Jun 14 18:03:43 2012 +0200
@@ -46,7 +46,9 @@
     ArithmeticCos(Double, Double),
     ArithmeticTan(Double, Double),
     ArithmeticSin(Double, Double),
-    GenericCallback(Object, Object, Object);
+    GenericCallback(Object, Object, Object),
+    LogPrimitive(Void, Int, Long, Boolean),
+    LogObject(Void, Object, Boolean, Boolean);
 
     public final Kind resultKind;
     public final Kind[] arguments;
@@ -55,4 +57,13 @@
         this.resultKind = resultKind;
         this.arguments = args;
     }
+
+    public boolean hasSideEffect() {
+        switch (this) {
+            case LogObject:
+            case LogPrimitive:
+                return false;
+        }
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Thu Jun 14 18:03:43 2012 +0200
@@ -24,7 +24,7 @@
 
 /**
  * Represents a constant (boxed) value, such as an integer, floating point number, or object reference,
- * within the compiler and across the compiler/runtime interface. Exports a set of {@code CiConstant}
+ * within the compiler and across the compiler/runtime interface. Exports a set of {@code Constant}
  * instances that represent frequently used constant values, such as {@link #ZERO}.
  */
 public final class Constant extends Value {
@@ -436,7 +436,7 @@
             case Object:
                 return forObject(value);
             default:
-                throw new RuntimeException("cannot create CiConstant for boxed " + kind + " value");
+                throw new RuntimeException("cannot create Constant for boxed " + kind + " value");
         }
     }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Thu Jun 14 18:03:43 2012 +0200
@@ -87,7 +87,7 @@
     /**
      * Looks up a constant at the specified index.
      * @param cpi the constant pool index
-     * @return the {@code CiConstant} instance representing the constant
+     * @return the {@code Constant} or {@code JavaType} instance representing the constant pool entry
      */
     Object lookupConstant(int cpi);
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Thu Jun 14 18:03:43 2012 +0200
@@ -56,7 +56,7 @@
     ResolvedJavaMethod getResolvedJavaMethod(Method reflectionMethod);
 
     /**
-     * Gets the length of the array that is wrapped in a CiConstant object.
+     * Gets the length of the array that is wrapped in a Constant object.
      */
     int getArrayLength(Constant array);
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Thu Jun 14 18:03:43 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 = null;
+    public static String HIRLowerNewInstance = "NewInstanceTest";
 
     /**
      * The profiling info cache directory.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Thu Jun 14 18:03:43 2012 +0200
@@ -32,7 +32,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.virtual.*;
 
 public class DebugInfoBuilder {
@@ -52,20 +51,13 @@
         VirtualObject[] virtualObjectsArray = null;
         if (virtualObjects.size() != 0) {
             // collect all VirtualObjectField instances:
-            IdentityHashMap<VirtualObjectNode, VirtualObjectFieldNode> objectStates = new IdentityHashMap<>();
+            IdentityHashMap<VirtualObjectNode, VirtualObjectState> objectStates = new IdentityHashMap<>();
             FrameState current = topState;
             do {
-                for (Node n : current.virtualObjectMappings()) {
-                    Node p = n;
-                    while (p instanceof PhiNode) {
-                        PhiNode phi = (PhiNode) p;
-                        assert phi.type() == PhiType.Virtual;
-                        p = phi.valueAt(0);
-                    }
-                    VirtualObjectFieldNode field = (VirtualObjectFieldNode) p;
+                for (VirtualObjectState state : current.virtualObjectMappings()) {
                     // null states occur for objects with 0 fields
-                    if (field != null && !objectStates.containsKey(field.object())) {
-                        objectStates.put(field.object(), field);
+                    if (!objectStates.containsKey(state.object())) {
+                        objectStates.put(state.object(), state);
                     }
                 }
                 current = current.outerFrameState();
@@ -87,20 +79,11 @@
                             entry.getValue().setValues(values);
                             if (values.length > 0) {
                                 changed = true;
-                                ValueNode currentField = objectStates.get(vobj);
+                                VirtualObjectState currentField = objectStates.get(vobj);
                                 assert currentField != null;
-                                do {
-                                    if (currentField instanceof VirtualObjectFieldNode) {
-                                        int index = ((VirtualObjectFieldNode) currentField).index();
-                                        if (values[index] == null) {
-                                            values[index] = toCiValue(((VirtualObjectFieldNode) currentField).input());
-                                        }
-                                        currentField = ((VirtualObjectFieldNode) currentField).lastState();
-                                    } else {
-                                        assert currentField instanceof PhiNode : currentField;
-                                        currentField = ((PhiNode) currentField).valueAt(0);
-                                    }
-                                } while (currentField != null);
+                                for (int i = 0; i < vobj.fieldsCount(); i++) {
+                                    values[i] = toCiValue(currentField.fields().get(i));
+                                }
                             }
                         }
                     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Jun 14 18:03:43 2012 +0200
@@ -381,7 +381,7 @@
             lastState = fs;
         }
 
-        List<Node> nodes = lir.nodesFor(block);
+        List<ScheduledNode> nodes = lir.nodesFor(block);
         for (int i = 0; i < nodes.size(); i++) {
             Node instr = nodes.get(i);
 
@@ -974,8 +974,6 @@
 
     @Override
     public void emitRuntimeCall(RuntimeCallNode x) {
-        // TODO Merge with emitCallToRuntime() method above.
-
         Value resultOperand = resultOperandFor(x.kind());
         CallingConvention cc = frameMap.registerConfig.getCallingConvention(RuntimeCall, x.call().arguments, target(), false);
         frameMap.callsMethod(cc, RuntimeCall);
@@ -996,6 +994,11 @@
 
             // TODO is it correct here that the pointerSlots are not passed to the oop map generation?
             info = stateFor(stateBeforeReturn, -1);
+        } else {
+            // Every runtime call needs an info
+            // TODO This is conservative. It's not needed for RuntimeCalls that are implemented purely in a stub
+            //       that does not trash any registers and does not call into the runtime.
+            info = state();
         }
 
         emitCall(x.call(), resultOperand, argList, Constant.forLong(0), info, null);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java	Thu Jun 14 18:03:43 2012 +0200
@@ -30,7 +30,6 @@
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
-import com.oracle.graal.nodes.util.*;
 
 
 public abstract class LoopFragment {
@@ -244,14 +243,8 @@
                     PhiNode phi = graph.add(vpn.type() == PhiType.Value ? new PhiNode(vpn.kind(), merge) : new PhiNode(vpn.type(), merge));
                     phi.addInput(vpn);
                     phi.addInput(newVpn);
-                    if (vpn.type() == PhiType.Value) {
-                        replaceWith = phi;
-                    } else {
-                        assert vpn.type() == PhiType.Virtual;
-                        ValueNode vof = GraphUtil.unProxify(vpn);
-                        ValueNode newVof = GraphUtil.unProxify(newVpn);
-                        replaceWith = GraphUtil.mergeVirtualChain(graph, vof, newVof, phi, earlyExit, newEarlyExit, merge);
-                    }
+                    assert vpn.type() == PhiType.Value;
+                    replaceWith = phi;
                 } else {
                     replaceWith = vpn.value();
                 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java	Thu Jun 14 18:03:43 2012 +0200
@@ -246,9 +246,6 @@
                 if (duplicateState != null) {
                     duplicateState.replaceFirstInput(phi, firstPhi); // fix the merge's state after
                 }
-                if (phi.type() == PhiType.Virtual) {
-                    initializer = GraphUtil.mergeVirtualChain(graph, firstPhi, newExitMerge);
-                }
                 mergedInitializers.put(phi, initializer);
             }
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BoxingEliminationPhase.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BoxingEliminationPhase.java	Thu Jun 14 18:03:43 2012 +0200
@@ -110,7 +110,7 @@
         assert boxNode.objectStamp().isExactType();
         virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type());
 
-        if (boxNode.usages().filter(isNotA(FrameState.class).nor(VirtualObjectFieldNode.class)).isNotEmpty()) {
+        if (boxNode.usages().filter(isNotA(VirtualState.class)).isNotEmpty()) {
             // Elimination failed, because boxing object escapes.
             return;
         }
@@ -125,7 +125,7 @@
     private static void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType) {
         ValueNode virtualValueNode = null;
         VirtualObjectNode virtualObjectNode = null;
-        for (Node n : boxNode.usages().filter(NodePredicates.isA(FrameState.class).or(VirtualObjectFieldNode.class)).snapshot()) {
+        for (Node n : boxNode.usages().filter(NodePredicates.isA(VirtualState.class)).snapshot()) {
             if (virtualValueNode == null) {
                 virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(exactType, replacement));
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Thu Jun 14 18:03:43 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.max.criutils.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.graph.*;
@@ -38,38 +37,34 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
+import com.oracle.max.criutils.*;
 
 
 public class EscapeAnalysisPhase extends Phase {
 
+    /**
+     * Encapsulates the state of the virtual object, which is updated while traversing the control flow graph.
+     */
     public static class BlockExitState implements MergeableState<BlockExitState> {
         public final ValueNode[] fieldState;
         public final VirtualObjectNode virtualObject;
-        public ValueNode virtualObjectField;
         public final Graph graph;
 
         public BlockExitState(EscapeField[] fields, VirtualObjectNode virtualObject) {
             this.fieldState = new ValueNode[fields.length];
             this.virtualObject = virtualObject;
-            this.virtualObjectField = null;
             this.graph = virtualObject.graph();
             for (int i = 0; i < fields.length; i++) {
                 fieldState[i] = ConstantNode.defaultForKind(fields[i].type().kind(), virtualObject.graph());
-                virtualObjectField = graph.add(new VirtualObjectFieldNode(virtualObject, virtualObjectField, fieldState[i], i));
             }
         }
 
         public BlockExitState(BlockExitState state) {
             this.fieldState = state.fieldState.clone();
             this.virtualObject = state.virtualObject;
-            this.virtualObjectField = state.virtualObjectField;
             this.graph = state.graph;
         }
 
-        public void updateField(int fieldIndex) {
-            virtualObjectField = graph.add(new VirtualObjectFieldNode(virtualObject, virtualObjectField, fieldState[fieldIndex], fieldIndex));
-        }
-
         @Override
         public BlockExitState clone() {
             return new BlockExitState(this);
@@ -77,14 +72,8 @@
 
         @Override
         public boolean merge(MergeNode merge, List<BlockExitState> withStates) {
-            PhiNode vobjPhi = null;
             PhiNode[] valuePhis = new PhiNode[fieldState.length];
             for (BlockExitState other : withStates) {
-                if (virtualObjectField != other.virtualObjectField && vobjPhi == null) {
-                    vobjPhi = graph.add(new PhiNode(PhiType.Virtual, merge));
-                    vobjPhi.addInput(virtualObjectField);
-                    virtualObjectField = vobjPhi;
-                }
                 for (int i2 = 0; i2 < fieldState.length; i2++) {
                     if (fieldState[i2] != other.fieldState[i2] && valuePhis[i2] == null) {
                         valuePhis[i2] = graph.add(new PhiNode(fieldState[i2].kind(), merge));
@@ -94,51 +83,27 @@
                 }
             }
             for (BlockExitState other : withStates) {
-                if (vobjPhi != null) {
-                    vobjPhi.addInput(other.virtualObjectField);
-                }
                 for (int i2 = 0; i2 < fieldState.length; i2++) {
                     if (valuePhis[i2] != null) {
                         valuePhis[i2].addInput(other.fieldState[i2]);
                     }
                 }
             }
-            assert vobjPhi == null || vobjPhi.valueCount() == withStates.size() + 1;
-            for (int i2 = 0; i2 < fieldState.length; i2++) {
-                if (valuePhis[i2] != null) {
-                    virtualObjectField = graph.add(new VirtualObjectFieldNode(virtualObject, virtualObjectField, valuePhis[i2], i2));
-                    assert valuePhis[i2].valueCount() == withStates.size() + 1;
-                }
-            }
             return true;
         }
 
         @Override
         public void loopBegin(LoopBeginNode loopBegin) {
-            assert virtualObjectField != null : "unexpected null virtualObjectField";
-            PhiNode vobjPhi = null;
-            vobjPhi = graph.add(new PhiNode(PhiType.Virtual, loopBegin));
-            vobjPhi.addInput(virtualObjectField);
-            virtualObjectField = vobjPhi;
             for (int i2 = 0; i2 < fieldState.length; i2++) {
                 PhiNode valuePhi = graph.add(new PhiNode(fieldState[i2].kind(), loopBegin));
                 valuePhi.addInput(fieldState[i2]);
                 fieldState[i2] = valuePhi;
-                updateField(i2);
             }
         }
 
         @Override
         public void loopEnds(LoopBeginNode loopBegin, List<BlockExitState> loopEndStates) {
-            while (!loopBegin.isPhiAtMerge(virtualObjectField)) {
-                if (virtualObjectField instanceof PhiNode) {
-                    virtualObjectField = ((PhiNode) virtualObjectField).valueAt(0);
-                } else {
-                    virtualObjectField = ((VirtualObjectFieldNode) virtualObjectField).lastState();
-                }
-            }
             for (BlockExitState loopEndState : loopEndStates) {
-                ((PhiNode) virtualObjectField).addInput(loopEndState.virtualObjectField);
                 for (int i2 = 0; i2 < fieldState.length; i2++) {
                     ((PhiNode) fieldState[i2]).addInput(loopEndState.fieldState[i2]);
                 }
@@ -175,6 +140,12 @@
             }
         }
 
+        private void process() {
+            for (Node usage : node.usages().snapshot()) {
+                op.beforeUpdate(node, usage);
+            }
+        }
+
         public void removeAllocation() {
             escapeFields = op.fields(node);
             for (int i = 0; i < escapeFields.length; i++) {
@@ -202,42 +173,21 @@
                 final PostOrderNodeIterator<?> iterator = new PostOrderNodeIterator<BlockExitState>(next, startState) {
                     @Override
                     protected void node(FixedNode curNode) {
-                        int changedField = op.updateState(virtual, curNode, fields, state.fieldState);
-                        if (changedField != -1) {
-                            state.updateField(changedField);
-                        }
+                        op.updateState(virtual, curNode, fields, state.fieldState);
                         if (curNode instanceof LoopExitNode) {
-                            state.virtualObjectField = graph.unique(new ValueProxyNode(state.virtualObjectField, (LoopExitNode) curNode, PhiType.Virtual));
                             for (int i = 0; i < state.fieldState.length; i++) {
                                 state.fieldState[i] = graph.unique(new ValueProxyNode(state.fieldState[i], (LoopExitNode) curNode, PhiType.Value));
                             }
                         }
                         if (!curNode.isDeleted() && curNode instanceof StateSplit && ((StateSplit) curNode).stateAfter() != null) {
-                            if (state.virtualObjectField != null) {
-                                ValueNode v = state.virtualObjectField;
-                                if (curNode instanceof LoopBeginNode) {
-                                    while (!((LoopBeginNode) curNode).isPhiAtMerge(v)) {
-                                        if (v instanceof PhiNode) {
-                                            v = ((PhiNode) v).valueAt(0);
-                                        } else {
-                                            v = ((VirtualObjectFieldNode) v).lastState();
-                                        }
-                                    }
-                                }
-                                ((StateSplit) curNode).stateAfter().addVirtualObjectMapping(v);
-                            }
+                            VirtualObjectState v = graph.add(new VirtualObjectState(virtual, state.fieldState));
+                            ((StateSplit) curNode).stateAfter().addVirtualObjectMapping(v);
                         }
                     }
                 };
                 iterator.apply();
             }
         }
-
-        private void process() {
-            for (Node usage : node.usages().snapshot()) {
-                op.beforeUpdate(node, usage);
-            }
-        }
     }
 
     private final TargetDescription target;
@@ -278,7 +228,7 @@
 
     private static Node escape(EscapeRecord record, Node usage) {
         final Node node = record.node;
-        if (usage instanceof FrameState) {
+        if (usage instanceof VirtualState) {
             assert usage.inputs().contains(node);
             return null;
         } else {
@@ -318,8 +268,6 @@
                     // in order to not escape, the access needs to have a valid constant index and either a store into node or be self-referencing
                     return EscapeOp.isValidConstantIndex(x) && x.value() != node ? null : x.array();
                 }
-            } else if (usage instanceof VirtualObjectFieldNode) {
-                return null;
             } else if (usage instanceof RegisterFinalizerNode) {
                 assert ((RegisterFinalizerNode) usage).object() == node;
                 return null;
@@ -467,7 +415,7 @@
         for (Node usage : node.usages().snapshot()) {
             boolean escapes = op.escape(node, usage);
             if (escapes) {
-                if (usage instanceof FrameState) {
+                if (usage instanceof VirtualState) {
                     // nothing to do...
                 } else if (usage instanceof MethodCallTargetNode) {
                     if (usage.usages().size() == 0) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java	Thu Jun 14 18:03:43 2012 +0200
@@ -49,7 +49,7 @@
     protected void run(StructuredGraph graph) {
         for (ReturnNode ret : graph.getNodes(ReturnNode.class)) {
             PlaceholderNode p = graph.add(new PlaceholderNode());
-            p.setStateAfter(graph.add(new FrameState(null, FrameState.AFTER_BCI, 0, 0, false, false)));
+            p.setStateAfter(graph.add(new FrameState(FrameState.AFTER_BCI)));
             graph.addBeforeFixed(ret, p);
         }
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/SnippetIntrinsificationPhase.java	Thu Jun 14 18:03:18 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,282 +0,0 @@
-/*
- * 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.phases;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.ConstantNodeParameter;
-import com.oracle.graal.graph.Node.Fold;
-import com.oracle.graal.graph.Node.NodeIntrinsic;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.util.*;
-
-public class SnippetIntrinsificationPhase extends Phase {
-
-    private final CodeCacheProvider runtime;
-    private final BoxingMethodPool pool;
-
-    public SnippetIntrinsificationPhase(CodeCacheProvider runtime, BoxingMethodPool pool) {
-        this.runtime = runtime;
-        this.pool = pool;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (Invoke i : graph.getInvokes()) {
-            tryIntrinsify(i);
-        }
-    }
-
-    private void tryIntrinsify(Invoke invoke) {
-        ResolvedJavaMethod target = invoke.callTarget().targetMethod();
-        NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class);
-        if (intrinsic != null) {
-            assert target.getAnnotation(Node.Fold.class) == null;
-
-            Class< ? >[] parameterTypes = CodeUtil.signatureToTypes(target.signature(), target.holder());
-
-            // Prepare the arguments for the reflective constructor call on the node class.
-            Object[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false);
-
-            // Create the new node instance.
-            Class< ? > c = getNodeClass(target, intrinsic);
-            Node newInstance = createNodeInstance(c, parameterTypes, nodeConstructorArguments);
-
-            // Replace the invoke with the new node.
-            invoke.node().graph().add(newInstance);
-            invoke.intrinsify(newInstance);
-
-            // Clean up checkcast instructions inserted by javac if the return type is generic.
-            cleanUpReturnCheckCast(newInstance);
-        } else if (target.getAnnotation(Node.Fold.class) != null) {
-            Class< ? >[] parameterTypes = CodeUtil.signatureToTypes(target.signature(), target.holder());
-
-            // Prepare the arguments for the reflective method call
-            Object[] arguments = prepareArguments(invoke, parameterTypes, target, true);
-            Object receiver = null;
-            if (!invoke.callTarget().isStatic()) {
-                receiver = arguments[0];
-                arguments = Arrays.asList(arguments).subList(1, arguments.length).toArray();
-            }
-
-            // Call the method
-            Constant constant = callMethod(target.signature().returnKind(), target.holder().toJava(), target.name(), parameterTypes, receiver, arguments);
-
-            if (constant != null) {
-                // Replace the invoke with the result of the call
-                ConstantNode node = ConstantNode.forCiConstant(constant, runtime, invoke.node().graph());
-                invoke.intrinsify(node);
-
-                // Clean up checkcast instructions inserted by javac if the return type is generic.
-                cleanUpReturnCheckCast(node);
-            } else {
-                // Remove the invoke
-                invoke.intrinsify(null);
-            }
-        }
-    }
-
-    /**
-     * Converts the arguments of an invoke node to object values suitable for use as the arguments
-     * to a reflective invocation of a Java constructor or method.
-     *
-     * @param folding specifies if the invocation is for handling a {@link Fold} annotation
-     */
-    private Object[] prepareArguments(Invoke invoke, Class< ? >[] parameterTypes, ResolvedJavaMethod target, boolean folding) {
-        NodeInputList<ValueNode> arguments = invoke.callTarget().arguments();
-        Object[] reflectionCallArguments = new Object[arguments.size()];
-        for (int i = 0; i < reflectionCallArguments.length; ++i) {
-            int parameterIndex = i;
-            if (!invoke.callTarget().isStatic()) {
-                parameterIndex--;
-            }
-            ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i));
-            if (folding || CodeUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) {
-                assert argument instanceof ConstantNode : "parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.callTarget().targetMethod() + ": " + argument;
-                ConstantNode constantNode = (ConstantNode) argument;
-                Constant constant = constantNode.asConstant();
-                Object o = constant.boxedValue();
-                if (o instanceof Class< ? >) {
-                    reflectionCallArguments[i] = runtime.getResolvedJavaType((Class< ? >) o);
-                    parameterTypes[i] = ResolvedJavaType.class;
-                } else {
-                    if (parameterTypes[i] == boolean.class) {
-                        reflectionCallArguments[i] = Boolean.valueOf(constant.asInt() != 0);
-                    } else if (parameterTypes[i] == byte.class) {
-                        reflectionCallArguments[i] = Byte.valueOf((byte) constant.asInt());
-                    } else if (parameterTypes[i] == short.class) {
-                        reflectionCallArguments[i] = Short.valueOf((short) constant.asInt());
-                    } else if (parameterTypes[i] == char.class) {
-                        reflectionCallArguments[i] = Character.valueOf((char) constant.asInt());
-                    } else {
-                        reflectionCallArguments[i] = o;
-                    }
-                }
-            } else {
-                reflectionCallArguments[i] = argument;
-                parameterTypes[i] = ValueNode.class;
-            }
-        }
-        return reflectionCallArguments;
-    }
-
-    private static Class< ? > getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) {
-        Class< ? > result = intrinsic.value();
-        if (result == NodeIntrinsic.class) {
-            result = target.holder().toJava();
-        }
-        assert Node.class.isAssignableFrom(result);
-        return result;
-    }
-
-    private ValueNode tryBoxingElimination(int parameterIndex, ResolvedJavaMethod target, ValueNode node) {
-        if (parameterIndex >= 0) {
-            Type type = target.getGenericParameterTypes()[parameterIndex];
-            if (type instanceof TypeVariable) {
-                TypeVariable typeVariable = (TypeVariable) type;
-                if (typeVariable.getBounds().length == 1) {
-                    Type boundType = typeVariable.getBounds()[0];
-                    if (boundType instanceof Class && ((Class) boundType).getSuperclass() == null) {
-                        // Unbound generic => try boxing elimination
-                        if (node.usages().size() == 2) {
-                            if (node instanceof Invoke) {
-                                Invoke invokeNode = (Invoke) node;
-                                MethodCallTargetNode callTarget = invokeNode.callTarget();
-                                if (pool.isBoxingMethod(callTarget.targetMethod())) {
-                                    FrameState stateAfter = invokeNode.stateAfter();
-                                    assert stateAfter.usages().size() == 1;
-                                    invokeNode.node().replaceAtUsages(null);
-                                    ValueNode result = callTarget.arguments().get(0);
-                                    StructuredGraph graph = (StructuredGraph) node.graph();
-                                    if (invokeNode instanceof InvokeWithExceptionNode) {
-                                        // Destroy exception edge & clear stateAfter.
-                                        InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
-
-                                        invokeWithExceptionNode.killExceptionEdge();
-                                        graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE);
-                                    } else {
-                                        graph.removeFixed((InvokeNode) invokeNode);
-                                    }
-                                    stateAfter.safeDelete();
-                                    GraphUtil.propagateKill(callTarget);
-                                    return result;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return node;
-    }
-
-    private static Node createNodeInstance(Class< ? > nodeClass, Class< ? >[] parameterTypes, Object[] nodeConstructorArguments) {
-        Constructor< ? > constructor;
-        try {
-            constructor = nodeClass.getDeclaredConstructor(parameterTypes);
-            constructor.setAccessible(true);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-        try {
-            return (ValueNode) constructor.newInstance(nodeConstructorArguments);
-        } catch (Exception e) {
-            throw new RuntimeException(constructor + Arrays.toString(nodeConstructorArguments), e);
-        }
-    }
-
-    /**
-     * Calls a Java method via reflection.
-     */
-    private static Constant callMethod(Kind returnKind, Class< ? > holder, String name, Class< ? >[] parameterTypes, Object receiver, Object[] arguments) {
-        Method method;
-        try {
-            method = holder.getDeclaredMethod(name, parameterTypes);
-            method.setAccessible(true);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-        try {
-            Object result = method.invoke(receiver, arguments);
-            if (result == null) {
-                return null;
-            }
-            return Constant.forBoxed(returnKind, result);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static String sourceLocation(Node n) {
-        String loc = GraphUtil.approxSourceLocation(n);
-        return loc == null ? "<unknown>" : loc;
-    }
-
-    public void cleanUpReturnCheckCast(Node newInstance) {
-        if (newInstance instanceof ValueNode && ((ValueNode) newInstance).kind() != Kind.Object) {
-            StructuredGraph graph = (StructuredGraph) newInstance.graph();
-            for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) {
-                for (ValueProxyNode vpn : checkCastNode.usages().filter(ValueProxyNode.class).snapshot()) {
-                    graph.replaceFloating(vpn, checkCastNode);
-                }
-                for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
-                    if (checkCastUsage instanceof ValueAnchorNode) {
-                        ValueAnchorNode valueAnchorNode = (ValueAnchorNode) checkCastUsage;
-                        graph.removeFixed(valueAnchorNode);
-                    } else if (checkCastUsage instanceof MethodCallTargetNode) {
-                        MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage;
-                        assert pool.isUnboxingMethod(checkCastCallTarget.targetMethod()) :
-                            "checkcast at " + sourceLocation(checkCastNode) + " not used by an unboxing method but by a call at " +
-                            sourceLocation(checkCastCallTarget.usages().first()) + " to " + checkCastCallTarget.targetMethod();
-                        Invoke invokeNode = checkCastCallTarget.invoke();
-                        invokeNode.node().replaceAtUsages(newInstance);
-                        if (invokeNode instanceof InvokeWithExceptionNode) {
-                            // Destroy exception edge & clear stateAfter.
-                            InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
-
-                            invokeWithExceptionNode.killExceptionEdge();
-                            graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE);
-                        } else {
-                            graph.removeFixed((InvokeNode) invokeNode);
-                        }
-                        checkCastCallTarget.safeDelete();
-                    } else if (checkCastUsage instanceof FrameState) {
-                        checkCastUsage.replaceFirstInput(checkCastNode, null);
-                    } else {
-                        assert false : sourceLocation(checkCastUsage) + " has unexpected usage " + checkCastUsage + " of checkcast at " + sourceLocation(checkCastNode);
-                    }
-                }
-                FixedNode next = checkCastNode.next();
-                checkCastNode.setNext(null);
-                checkCastNode.replaceAtPredecessor(next);
-                GraphUtil.killCFG(checkCastNode);
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/SchedulePhase.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/SchedulePhase.java	Thu Jun 14 18:03:43 2012 +0200
@@ -41,7 +41,7 @@
     /**
      * Map from blocks to the nodes in each block.
      */
-    private BlockMap<List<Node>> blockToNodesMap;
+    private BlockMap<List<ScheduledNode>> blockToNodesMap;
 
     public SchedulePhase() {
         super("Schedule");
@@ -57,17 +57,20 @@
         sortNodesWithinBlocks(graph);
     }
 
+    /**
+     * Sets {@link ScheduledNode#scheduledNext} on all scheduled nodes in all blocks using the scheduling built by @link {@link #run(StructuredGraph)}.
+     * This method should thus only be called when run has been successfully executed.
+     */
     public void scheduleGraph() {
+        assert blockToNodesMap != null : "cannot set scheduledNext before run has been executed";
         for (Block block : cfg.getBlocks()) {
-            List<Node> nodeList = blockToNodesMap.get(block);
+            List<ScheduledNode> nodeList = blockToNodesMap.get(block);
             ScheduledNode last = null;
-            for (Node node : nodeList) {
-                if (!(node instanceof FrameState)) {
-                    if (last != null) {
-                        last.setScheduledNext((ScheduledNode) node);
-                    }
-                    last = (ScheduledNode) node;
+            for (ScheduledNode node : nodeList) {
+                if (last != null) {
+                    last.setScheduledNext(node);
                 }
+                last = node;
             }
         }
     }
@@ -79,79 +82,86 @@
     /**
      * Gets the map from each block to the nodes in the block.
      */
-    public BlockMap<List<Node>> getBlockToNodesMap() {
+    public BlockMap<List<ScheduledNode>> getBlockToNodesMap() {
         return blockToNodesMap;
     }
 
     /**
      * Gets the nodes in a given block.
      */
-    public List<Node> nodesFor(Block block) {
+    public List<ScheduledNode> nodesFor(Block block) {
         return blockToNodesMap.get(block);
     }
 
     private void assignBlockToNodes(StructuredGraph graph) {
         for (Block block : cfg.getBlocks()) {
-            List<Node> nodes = new ArrayList<>();
+            List<ScheduledNode> nodes = new ArrayList<>();
             assert blockToNodesMap.get(block) == null;
             blockToNodesMap.put(block, nodes);
-            for (Node node : block.getNodes()) {
+            for (FixedNode node : block.getNodes()) {
                 nodes.add(node);
             }
         }
 
         for (Node n : graph.getNodes()) {
-            assignBlockToNode(n);
+            if (n instanceof ScheduledNode) {
+                assignBlockToNode((ScheduledNode) n);
+            }
         }
     }
 
-    private void assignBlockToNode(Node n) {
-        if (n == null) {
-            return;
-        }
+    /**
+     * Assigns a block to the given node. This method expects that PhiNodes and FixedNodes are already assigned to a
+     * block, since they should already have been placed by {@link ControlFlowGraph#identifyBlocks()}.
+     * This method will also try to
+     */
+    private void assignBlockToNode(ScheduledNode node) {
+        assert !node.isDeleted();
 
-        assert !n.isDeleted();
-
-        Block prevBlock = cfg.getNodeToBlock().get(n);
+        Block prevBlock = cfg.getNodeToBlock().get(node);
         if (prevBlock != null) {
             return;
         }
-        assert !(n instanceof PhiNode) : n;
-        assert !(n instanceof MergeNode);
+        // PhiNodes and FixedNodes should already have been placed in blocks by ControlFlowGraph.identifyBlocks
+        assert !(node instanceof PhiNode) : node;
+        assert !(node instanceof FixedNode) : node;
         // if in CFG, schedule at the latest position possible in the outermost loop possible
-        Block latestBlock = latestBlock(n);
+        Block latestBlock = latestBlock(node);
         Block block;
         if (latestBlock == null) {
-            block = earliestBlock(n);
-        } else if (GraalOptions.ScheduleOutOfLoops && !(n instanceof VirtualObjectFieldNode) && !(n instanceof VirtualObjectNode)) {
-            Block earliestBlock = earliestBlock(n);
-            block = scheduleOutOfLoops(n, latestBlock, earliestBlock);
-            assert earliestBlock.dominates(block) : "Graph can not be scheduled : inconsistent for " + n;
+            block = earliestBlock(node);
+        } else if (GraalOptions.ScheduleOutOfLoops && !(node instanceof VirtualObjectNode)) {
+            Block earliestBlock = earliestBlock(node);
+            block = scheduleOutOfLoops(node, latestBlock, earliestBlock);
+            assert earliestBlock.dominates(block) : "Graph can not be scheduled : inconsistent for " + node + " (" + earliestBlock + " needs to dominate " + block + ")";
         } else {
             block = latestBlock;
         }
-        cfg.getNodeToBlock().set(n, block);
-        blockToNodesMap.get(block).add(n);
+        cfg.getNodeToBlock().set(node, block);
+        blockToNodesMap.get(block).add(node);
     }
 
-    private Block latestBlock(Node n) {
-        Block block = null;
-        for (Node succ : n.successors()) {
-            if (succ == null) {
-                continue;
-            }
-            assignBlockToNode(succ);
-            block = getCommonDominator(block, cfg.getNodeToBlock().get(succ));
+    /**
+     * Calculates the last block that the given node could be scheduled in, i.e., the common dominator of all usages.
+     * To do so all usages are also assigned to blocks.
+     */
+    private Block latestBlock(ScheduledNode node) {
+        CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(null);
+        for (Node succ : node.successors().nonNull()) {
+            assert cfg.getNodeToBlock().get(succ) != null;
+            cdbc.apply(cfg.getNodeToBlock().get(succ));
         }
-        ensureScheduledUsages(n);
-        CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(block);
-        for (Node usage : n.usages()) {
-            blocksForUsage(n, usage, cdbc);
+        ensureScheduledUsages(node);
+        for (Node usage : node.usages()) {
+            blocksForUsage(node, usage, cdbc);
         }
         return cdbc.block;
     }
 
-    private class CommonDominatorBlockClosure implements BlockClosure {
+    /**
+     * A closure that will calculate the common dominator of all blocks passed to its {@link #apply(Block)} method.
+     */
+    private static class CommonDominatorBlockClosure implements BlockClosure {
         public Block block;
         public CommonDominatorBlockClosure(Block block) {
             this.block = block;
@@ -162,42 +172,45 @@
         }
     }
 
-    private Block earliestBlock(Node n) {
-        Block earliest = cfg.getNodeToBlock().get(n);
+    /**
+     * Determines the earliest block in which the given node can be scheduled.
+     */
+    private Block earliestBlock(Node node) {
+        Block earliest = cfg.getNodeToBlock().get(node);
         if (earliest != null) {
             return earliest;
         }
-        earliest = earliestCache.get(n);
+        earliest = earliestCache.get(node);
         if (earliest != null) {
             return earliest;
         }
-        BitSet bits = new BitSet(cfg.getBlocks().length);
-        ArrayList<Node> before = new ArrayList<>();
-        if (n.predecessor() != null) {
-            before.add(n.predecessor());
-        }
-        for (Node input : n.inputs()) {
-            before.add(input);
-        }
-        for (Node pred : before) {
-            if (pred == null) {
-                continue;
-            }
-            Block b = earliestBlock(pred);
-            if (!bits.get(b.getId())) {
-                earliest = b;
+        /*
+         * All inputs must be in a dominating block, otherwise the graph cannot be scheduled. This implies that the
+         * inputs' blocks have a total ordering via their dominance relation. So in order to find the earliest block
+         * placement for this node we need to find the input block that is dominated by all other input blocks.
+         *
+         * While iterating over the inputs a set of dominator blocks of the current earliest placement is maintained.
+         * When the block of an input is not within this set, it becomes the current earliest placement and the list of
+         * dominator blocks is updated.
+         */
+        BitSet dominators = new BitSet(cfg.getBlocks().length);
+
+        assert node.predecessor() == null;
+        for (Node input : node.inputs().nonNull()) {
+            assert input instanceof ValueNode;
+            Block inputEarliest = earliestBlock(input);
+            if (!dominators.get(inputEarliest.getId())) {
+                earliest = inputEarliest;
                 do {
-                    bits.set(b.getId());
-                    b = b.getDominator();
-                } while(b != null && !bits.get(b.getId()));
+                    dominators.set(inputEarliest.getId());
+                    inputEarliest = inputEarliest.getDominator();
+                } while(inputEarliest != null && !dominators.get(inputEarliest.getId()));
             }
         }
         if (earliest == null) {
-            Block start = cfg.getNodeToBlock().get(((StructuredGraph) n.graph()).start());
-            assert start != null;
-            return start;
+            earliest = cfg.getStartBlock();
         }
-        earliestCache.set(n, earliest);
+        earliestCache.set(node, earliest);
         return earliest;
     }
 
@@ -216,8 +229,20 @@
         return result;
     }
 
-    private void blocksForUsage(Node node, Node usage, BlockClosure closure) {
+    /**
+     * Passes all blocks that a specific usage of a node is in to a given closure.
+     * This is more complex than just taking the usage's block because of of PhiNodes and FrameStates.
+     *
+     * @param node the node that needs to be scheduled
+     * @param usage the usage whose blocks need to be considered
+     * @param closure the closure that will be called for each block
+     */
+    private void blocksForUsage(ScheduledNode node, Node usage, BlockClosure closure) {
+        assert !(node instanceof PhiNode);
+
         if (usage instanceof PhiNode) {
+            // An input to a PhiNode is used at the end of the predecessor block that corresponds to the PhiNode input.
+            // One PhiNode can use an input multiple times, the closure will be called for each usage.
             PhiNode phi = (PhiNode) usage;
             MergeNode merge = phi.merge();
             Block mergeBlock = cfg.getNodeToBlock().get(merge);
@@ -235,22 +260,38 @@
                     closure.apply(mergeBlock.getPredecessors().get(i));
                 }
             }
-        } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) {
-            MergeNode merge = ((FrameState) usage).block();
-            Block block = null;
-            for (Node pred : merge.cfgPredecessors()) {
-                block = getCommonDominator(block, cfg.getNodeToBlock().get(pred));
+        } else if (usage instanceof VirtualState) {
+            // The following logic does not work if node is a PhiNode, but this method is never called for PhiNodes.
+            for (Node unscheduledUsage : usage.usages()) {
+                if (unscheduledUsage instanceof VirtualState) {
+                    // If a FrameState is an outer FrameState this method behaves as if the inner FrameState was the actual usage, by recursing.
+                    blocksForUsage(node, unscheduledUsage, closure);
+                } else if (unscheduledUsage instanceof MergeNode) {
+                    // Only FrameStates can be connected to MergeNodes.
+                    assert usage instanceof FrameState;
+                    // If a FrameState belongs to a MergeNode then it's inputs will be placed at the common dominator of all EndNodes.
+                    for (Node pred : unscheduledUsage.cfgPredecessors()) {
+                        closure.apply(cfg.getNodeToBlock().get(pred));
+                    }
+                } else {
+                    // For the time being, only FrameStates can be connected to StateSplits.
+                    assert usage instanceof FrameState;
+                    assert unscheduledUsage instanceof StateSplit;
+                    // Otherwise: Put the input into the same block as the usage.
+                    assignBlockToNode((ScheduledNode) unscheduledUsage);
+                    closure.apply(cfg.getNodeToBlock().get(unscheduledUsage));
+                }
             }
-            closure.apply(block);
         } else {
-            assignBlockToNode(usage);
+            // All other types of usages: Put the input into the same block as the usage.
+            assignBlockToNode((ScheduledNode) usage);
             closure.apply(cfg.getNodeToBlock().get(usage));
         }
     }
 
     private void ensureScheduledUsages(Node node) {
-        for (Node usage : node.usages().snapshot()) {
-            assignBlockToNode(usage);
+        for (Node usage : node.usages().filter(ScheduledNode.class)) {
+            assignBlockToNode((ScheduledNode) usage);
         }
         // now true usages are ready
     }
@@ -266,21 +307,25 @@
     }
 
     private void sortNodesWithinBlocks(StructuredGraph graph) {
-        NodeBitMap map = graph.createNodeBitMap();
+        NodeBitMap visited = graph.createNodeBitMap();
         for (Block b : cfg.getBlocks()) {
-            sortNodesWithinBlocks(b, map);
+            sortNodesWithinBlock(b, visited);
         }
     }
 
-    private void sortNodesWithinBlocks(Block b, NodeBitMap map) {
-        List<Node> instructions = blockToNodesMap.get(b);
-        List<Node> sortedInstructions = new ArrayList<>(instructions.size() + 2);
+    /**
+     * Sorts the nodes within a block by adding the nodes to a list in a post-order iteration over all inputs.
+     * This means that a node is added to the list after all its inputs have been processed.
+     */
+    private void sortNodesWithinBlock(Block b, NodeBitMap visited) {
+        List<ScheduledNode> instructions = blockToNodesMap.get(b);
+        List<ScheduledNode> sortedInstructions = new ArrayList<>(instructions.size() + 2);
 
-        assert !map.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b;
-        assert !map.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b;
+        assert !visited.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b;
+        assert !visited.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b;
 
-        for (Node i : instructions) {
-            addToSorting(b, i, sortedInstructions, map);
+        for (ScheduledNode i : instructions) {
+            addToSorting(b, i, sortedInstructions, visited);
         }
 
         // Make sure that last node gets really last (i.e. when a frame state successor hangs off it).
@@ -310,32 +355,45 @@
         blockToNodesMap.put(b, sortedInstructions);
     }
 
-    private void addToSorting(Block b, Node i, List<Node> sortedInstructions, NodeBitMap map) {
-        if (i == null || map.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode || i instanceof LocalNode) {
+    private void addUnscheduledToSorting(Block b, VirtualState state, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
+        if (state != null) {
+            // UnscheduledNodes should never be marked as visited.
+            assert !visited.isMarked(state);
+
+            for (Node input : state.inputs()) {
+                if (input instanceof VirtualState) {
+                    addUnscheduledToSorting(b, (VirtualState) input, sortedInstructions, visited);
+                } else {
+                    addToSorting(b, (ScheduledNode) input, sortedInstructions, visited);
+                }
+            }
+        }
+    }
+
+    private void addToSorting(Block b, ScheduledNode i, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
+        if (i == null || visited.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode || i instanceof LocalNode) {
             return;
         }
 
         FrameState state = null;
-        WriteNode writeNode = null;
+        WriteNode write = null;
         for (Node input : i.inputs()) {
-            if (input instanceof WriteNode && !map.isMarked(input) && cfg.getNodeToBlock().get(input) == b) {
-                writeNode = (WriteNode) input;
+            if (input instanceof WriteNode && !visited.isMarked(input) && cfg.getNodeToBlock().get(input) == b) {
+                assert write == null;
+                write = (WriteNode) input;
             } else if (input instanceof FrameState) {
+                assert state == null;
                 state = (FrameState) input;
             } else {
-                addToSorting(b, input, sortedInstructions, map);
+                addToSorting(b, (ScheduledNode) input, sortedInstructions, visited);
             }
         }
 
-        if (i.predecessor() != null) {
-            addToSorting(b, i.predecessor(), sortedInstructions, map);
-        }
-
-        map.mark(i);
-
-        addToSorting(b, state, sortedInstructions, map);
-        assert writeNode == null || !map.isMarked(writeNode);
-        addToSorting(b, writeNode, sortedInstructions, map);
+        addToSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited);
+        visited.mark(i);
+        addUnscheduledToSorting(b, state, sortedInstructions, visited);
+        assert write == null || !visited.isMarked(write);
+        addToSorting(b, write, sortedInstructions, visited);
 
         // Now predecessors and inputs are scheduled => we can add this node.
         sortedInstructions.add(i);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Thu Jun 14 18:03:43 2012 +0200
@@ -90,27 +90,6 @@
         Class value() default NodeIntrinsic.class;
     }
 
-
-    /**
-     * Annotates a method replaced by a compile-time constant.
-     * A (resolved) call to the annotated method is replaced
-     * with a constant obtained by calling the annotated method via reflection.
-     *
-     * All arguments to such a method (including the receiver if applicable)
-     * must be compile-time constants.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.METHOD)
-    public static @interface Fold {
-    }
-
-
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.METHOD)
-    public static @interface NodePhase {
-        Class value() default NodePhase.class;
-    }
-
     public interface ValueNumberable {}
 
     public interface IterableNodeType {}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Thu Jun 14 18:03:43 2012 +0200
@@ -21,11 +21,7 @@
  * questions.
  */
 package com.oracle.graal.graph;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
+import java.util.*;
 
 import com.oracle.graal.graph.iterators.*;
 
@@ -60,6 +56,7 @@
             this.nodes = new Node[elements.length];
             for (int i = 0; i < elements.length; i++) {
                 this.nodes[i] = elements[i];
+                assert this.nodes[i] == null || !this.nodes[i].isDeleted();
             }
         }
     }
@@ -75,6 +72,7 @@
             this.nodes = new Node[elements.size()];
             for (int i = 0; i < elements.size(); i++) {
                 this.nodes[i] = elements.get(i);
+                assert this.nodes[i] == null || !this.nodes[i].isDeleted();
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Jun 14 18:03:43 2012 +0200
@@ -154,7 +154,7 @@
                 final CodeInfo[] info = Debug.isDumpEnabled() ? new CodeInfo[1] : null;
                 compiler.getRuntime().installMethod(method, tm, info);
                 if (info != null) {
-                    Debug.dump(info[0], "After code installation");
+                    Debug.dump(new Object[] {tm, info[0]}, "After code installation");
                 }
             }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Jun 14 18:03:43 2012 +0200
@@ -41,6 +41,7 @@
     public boolean useFastLocking;
     public boolean useFastNewObjectArray;
     public boolean useFastNewTypeArray;
+    public boolean useTLAB;
 
     // offsets, ...
     public int vmPageSize;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Jun 14 18:03:43 2012 +0200
@@ -112,8 +112,9 @@
                 @Override
                 public void run() {
                     VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime);
-                    GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget());
-                    runtime.installSnippets();
+                    SnippetInstaller installer = new SnippetInstaller(runtime, runtime.getCompiler().getTarget());
+                    GraalIntrinsics.installIntrinsics(installer);
+                    runtime.installSnippets(installer);
                 }
             });
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jun 14 18:03:43 2012 +0200
@@ -68,14 +68,14 @@
         System.setProperty(Backend.BACKEND_CLASS_PROPERTY, HotSpotAMD64Backend.class.getName());
     }
 
-    public void installSnippets() {
-        Snippets.install(this, compiler.getTarget(), new SystemSnippets());
-        Snippets.install(this, compiler.getTarget(), new UnsafeSnippets());
-        Snippets.install(this, compiler.getTarget(), new ArrayCopySnippets());
-        Snippets.install(this, compiler.getTarget(), new CheckCastSnippets());
-        Snippets.install(this, compiler.getTarget(), new NewInstanceSnippets());
+    public void installSnippets(SnippetInstaller installer) {
+        installer.install(SystemSnippets.class);
+        installer.install(UnsafeSnippets.class);
+        installer.install(ArrayCopySnippets.class);
+        installer.install(CheckCastSnippets.class);
+        installer.install(NewInstanceSnippets.class);
         checkcastSnippets = new CheckCastSnippets.Templates(this);
-        newInstanceSnippets = new NewInstanceSnippets.Templates(this);
+        newInstanceSnippets = new NewInstanceSnippets.Templates(this, config.useTLAB);
     }
 
 
@@ -308,7 +308,7 @@
                 if (arrayType != null && array.objectStamp().isExactType()) {
                     ResolvedJavaType elementType = arrayType.componentType();
                     if (elementType.superType() != null) {
-                        ConstantNode type = ConstantNode.forCiConstant(elementType.getEncoding(Representation.ObjectHub), this, graph);
+                        ConstantNode type = ConstantNode.forConstant(elementType.getEncoding(Representation.ObjectHub), this, graph);
                         checkcast = graph.add(new CheckCastNode(type, elementType, value));
                         graph.addBeforeFixed(storeIndexed, checkcast);
                         value = checkcast;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Thu Jun 14 18:03:43 2012 +0200
@@ -49,7 +49,8 @@
     public void generate(LIRGenerator gen) {
         Variable result = gen.newVariable(Kind.Object);
         gen.emitMove(gen.operand(hub), AMD64.rdx.asValue());
-        AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue());
+        LIRDebugInfo info = gen.state();
+        AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue(), info);
         gen.append(op);
         gen.setResult(this, result);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Thu Jun 14 18:03:43 2012 +0200
@@ -22,13 +22,13 @@
  */
 package com.oracle.graal.hotspot.snippets;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.Node.Fold;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.snippets.*;
+import com.oracle.graal.snippets.Snippet.Fold;
 
 
 @SuppressWarnings("unused")
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Thu Jun 14 18:03:43 2012 +0200
@@ -38,7 +38,6 @@
 import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Fold;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
@@ -46,6 +45,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
+import com.oracle.graal.snippets.Snippet.Fold;
 import com.oracle.graal.snippets.Snippet.Parameter;
 import com.oracle.graal.snippets.SnippetTemplate.Arguments;
 import com.oracle.graal.snippets.SnippetTemplate.Cache;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java	Thu Jun 14 18:03:43 2012 +0200
@@ -37,7 +37,6 @@
 import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Fold;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
@@ -45,6 +44,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
+import com.oracle.graal.snippets.Snippet.Fold;
 import com.oracle.graal.snippets.Snippet.Parameter;
 import com.oracle.graal.snippets.SnippetTemplate.Arguments;
 import com.oracle.graal.snippets.SnippetTemplate.Cache;
@@ -55,32 +55,46 @@
  */
 public class NewInstanceSnippets implements SnippetsInterface {
 
-    /**
-     * Type test used when the type being tested against is a final type.
-     */
+    private static final boolean LOG_ALLOCATION = Boolean.getBoolean("graal.traceAllocation");
+
     @Snippet
-    public static Object newInstance(@Parameter("hub") Object hub, @ConstantParameter("size") int size, @ConstantParameter("checkInit") boolean checkInit) {
+    public static Object newInstance(
+                    @Parameter("hub") Object hub,
+                    @ConstantParameter("size") int size,
+                    @ConstantParameter("checkInit") boolean checkInit,
+                    @ConstantParameter("useTLAB") boolean useTLAB,
+                    @ConstantParameter("logType") String logType) {
+
         if (checkInit) {
             int klassState = load(hub, 0, klassStateOffset(), Kind.Int);
             if (klassState != klassStateFullyInitialized()) {
-                Object instance = NewInstanceStubCall.call(hub);
-                return formatInstance(hub, size, instance);
+                if (logType != null) {
+                    Log.print(logType);
+                    Log.println(" - uninitialized");
+                }
+                return NewInstanceStubCall.call(hub);
             }
         }
 
-        Word thread = asWord(register(r15, wordKind()));
-        Word top = loadWord(thread, threadTlabTopOffset());
-        Word end = loadWord(thread, threadTlabEndOffset());
-        Word newTop = top.plus(size);
-        Object instance;
-        if (newTop.cmp(BE, end)) {
-            instance = cast(top, Object.class);
-            store(thread, 0, threadTlabTopOffset(), newTop);
+        if (useTLAB) {
+            Word thread = asWord(register(r15, wordKind()));
+            Word top = loadWord(thread, threadTlabTopOffset());
+            Word end = loadWord(thread, threadTlabEndOffset());
+            Word newTop = top.plus(size);
+            if (newTop.cmp(BE, end)) {
+                Object instance = cast(top, Object.class);
+                store(thread, 0, threadTlabTopOffset(), newTop);
+                return formatInstance(hub, size, instance, logType);
+            } else {
+                if (logType != null) {
+                    Log.print(logType);
+                    Log.println(" - stub allocate");
+                }
+                return NewInstanceStubCall.call(hub);
+            }
         } else {
-            instance = NewInstanceStubCall.call(hub);
+            return NewInstanceStubCall.call(hub);
         }
-
-        return formatInstance(hub, size, instance);
     }
 
     private static Word asWord(Object object) {
@@ -94,7 +108,7 @@
     /**
      * Formats the header of a created instance and zeroes out its body.
      */
-    private static Object formatInstance(Object hub, int size, Object instance) {
+    private static Object formatInstance(Object hub, int size, Object instance, String logType) {
         Word headerPrototype = cast(load(hub, 0, instanceHeaderPrototypeOffset(), wordKind()), Word.class);
         store(instance, 0, 0, headerPrototype);
         store(instance, 0, hubOffset(), hub);
@@ -102,6 +116,12 @@
         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;
     }
 
@@ -150,12 +170,14 @@
         private final Cache cache;
         private final ResolvedJavaMethod newInstance;
         private final CodeCacheProvider runtime;
+        private final boolean useTLAB;
 
-        public Templates(CodeCacheProvider runtime) {
+        public Templates(CodeCacheProvider runtime, boolean useTLAB) {
             this.runtime = runtime;
             this.cache = new Cache(runtime);
+            this.useTLAB = useTLAB;
             try {
-                newInstance = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("newInstance", Object.class, int.class, boolean.class));
+                newInstance = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("newInstance", Object.class, int.class, boolean.class, boolean.class, String.class));
             } catch (NoSuchMethodException e) {
                 throw new GraalInternalError(e);
             }
@@ -170,10 +192,11 @@
             HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) newInstanceNode.instanceClass();
             HotSpotKlassOop hub = type.klassOop();
             int instanceSize = type.instanceSize();
-            Key key = new Key(newInstance).add("size", instanceSize).add("checkInit", !type.isInitialized());
+            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);
             template.instantiate(runtime, newInstanceNode, newInstanceNode, arguments);
             new DeadCodeEliminationPhase().apply(graph);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java	Thu Jun 14 18:03:43 2012 +0200
@@ -33,11 +33,11 @@
 public class SystemSnippets implements SnippetsInterface {
 
     public static long currentTimeMillis() {
-        return RuntimeCallNode.performCall(RuntimeCall.JavaTimeMillis);
+        return RuntimeCallNode.callLong(RuntimeCall.JavaTimeMillis);
     }
 
     public static long nanoTime() {
-        return RuntimeCallNode.performCall(RuntimeCall.JavaTimeNanos);
+        return RuntimeCallNode.callLong(RuntimeCall.JavaTimeNanos);
     }
 
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java	Thu Jun 14 18:03:43 2012 +0200
@@ -29,6 +29,7 @@
 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.*;
@@ -38,8 +39,8 @@
  * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp.
  */
 public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction {
-    public AMD64NewInstanceStubCallOp(Value result, Value hub) {
-        super("NEW_INSTANCE", new Value[] {result}, null, new Value[] {hub}, NO_OPERANDS, NO_OPERANDS);
+    public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRDebugInfo info) {
+        super("NEW_INSTANCE", new Value[] {result}, info, new Value[] {hub}, NO_OPERANDS, NO_OPERANDS);
     }
 
     @Override
@@ -50,7 +51,7 @@
         // rdx: (in) hub
         // rax: (out) result
         assert asRegister(hub) == AMD64.rdx;
-        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, null);
+        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, info);
         if (asRegister(result) != AMD64.rax) {
             masm.movq(asRegister(result), AMD64.rax);
         }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Thu Jun 14 18:03:43 2012 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.type.*;
 
 public class FrameStateBuilder {
@@ -155,7 +156,7 @@
 
         } else if (block.isPhiAtMerge(currentValue)) {
             if (otherValue == null || currentValue.kind() != otherValue.kind()) {
-                deletePhi((PhiNode) currentValue);
+                propagateDelete((PhiNode) currentValue);
                 return null;
             }
             ((PhiNode) currentValue).addInput(otherValue);
@@ -180,45 +181,21 @@
         }
     }
 
-    private void deletePhi(PhiNode phi) {
-        if (phi.isDeleted()) {
+    private void propagateDelete(FloatingNode node) {
+        assert node instanceof PhiNode || node instanceof ValueProxyNode;
+        if (node.isDeleted()) {
             return;
         }
         // Collect all phi functions that use this phi so that we can delete them recursively (after we delete ourselfs to avoid circles).
-        List<PhiNode> phiUsages = phi.usages().filter(PhiNode.class).snapshot();
-        List<ValueProxyNode> vpnUsages = phi.usages().filter(ValueProxyNode.class).snapshot();
+        List<FloatingNode> propagateUsages = node.usages().filter(FloatingNode.class).filter(isA(PhiNode.class).or(ValueProxyNode.class)).snapshot();
 
         // Remove the phi function from all FrameStates where it is used and then delete it.
-        assert phi.usages().filter(isNotA(FrameState.class).nor(PhiNode.class).nor(ValueProxyNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states";
-        phi.replaceAtUsages(null);
-        phi.safeDelete();
-
-        for (PhiNode phiUsage : phiUsages) {
-            deletePhi(phiUsage);
-        }
-        for (ValueProxyNode proxyUsage : vpnUsages) {
-            deleteProxy(proxyUsage);
-        }
-    }
+        assert node.usages().filter(isNotA(FrameState.class).nor(PhiNode.class).nor(ValueProxyNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states";
+        node.replaceAtUsages(null);
+        node.safeDelete();
 
-    private void deleteProxy(ValueProxyNode proxy) {
-        if (proxy.isDeleted()) {
-            return;
-        }
-        // Collect all phi functions that use this phi so that we can delete them recursively (after we delete ourselfs to avoid circles).
-        List<PhiNode> phiUsages = proxy.usages().filter(PhiNode.class).snapshot();
-        List<ValueProxyNode> vpnUsages = proxy.usages().filter(ValueProxyNode.class).snapshot();
-
-        // Remove the proxy function from all FrameStates where it is used and then delete it.
-        assert proxy.usages().filter(isNotA(FrameState.class).nor(PhiNode.class).nor(ValueProxyNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states";
-        proxy.replaceAtUsages(null);
-        proxy.safeDelete();
-
-        for (PhiNode phiUsage : phiUsages) {
-            deletePhi(phiUsage);
-        }
-        for (ValueProxyNode proxyUsage : vpnUsages) {
-            deleteProxy(proxyUsage);
+        for (FloatingNode phiUsage : propagateUsages) {
+            propagateDelete(phiUsage);
         }
     }
 
@@ -262,7 +239,7 @@
     public void cleanupDeletedPhis() {
         for (int i = 0; i < localsSize(); i++) {
             if (localAt(i) != null && localAt(i).isDeleted()) {
-                assert localAt(i) instanceof PhiNode : "Only phi functions can be deleted during parsing";
+                assert localAt(i) instanceof PhiNode || localAt(i) instanceof ValueProxyNode : "Only phi and value proxies can be deleted during parsing: " + localAt(i);
                 storeLocal(i, null);
             }
         }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Jun 14 18:03:43 2012 +0200
@@ -284,7 +284,7 @@
             // this is a load of class constant which might be unresolved
             JavaType riType = (JavaType) con;
             if (riType instanceof ResolvedJavaType) {
-                frameState.push(Kind.Object, append(ConstantNode.forCiConstant(((ResolvedJavaType) riType).getEncoding(Representation.JavaClass), runtime, currentGraph)));
+                frameState.push(Kind.Object, append(ConstantNode.forConstant(((ResolvedJavaType) riType).getEncoding(Representation.JavaClass), runtime, currentGraph)));
             } else {
                 append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved, graphId)));
                 frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph)));
@@ -1097,7 +1097,7 @@
     }
 
     private ConstantNode appendConstant(Constant constant) {
-        return ConstantNode.forCiConstant(constant, runtime, currentGraph);
+        return ConstantNode.forConstant(constant, runtime, currentGraph);
     }
 
     private ValueNode append(FixedNode fixed) {
@@ -1274,7 +1274,7 @@
 
     private ValueNode synchronizedObject(FrameStateBuilder state, ResolvedJavaMethod target) {
         if (isStatic(target.accessFlags())) {
-            return append(ConstantNode.forCiConstant(target.holder().getEncoding(Representation.JavaClass), runtime, currentGraph));
+            return append(ConstantNode.forConstant(target.holder().getEncoding(Representation.JavaClass), runtime, currentGraph));
         } else {
             return state.loadLocal(0);
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Thu Jun 14 18:03:43 2012 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.cfg.*;
+import com.oracle.graal.nodes.*;
 
 /**
  * This class implements the overall container for the LIR graph
@@ -42,7 +43,7 @@
      * The nodes for the blocks.
      * TODO: This should go away, we want all nodes connected with a next-pointer.
      */
-    private final BlockMap<List<Node>> blockToNodesMap;
+    private final BlockMap<List<ScheduledNode>> blockToNodesMap;
 
     /**
      * The linear-scan ordered list of blocks.
@@ -87,7 +88,7 @@
      * @param numLoops number of loops
      * @param compilation the compilation
      */
-    public LIR(ControlFlowGraph cfg, BlockMap<List<Node>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder) {
+    public LIR(ControlFlowGraph cfg, BlockMap<List<ScheduledNode>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder) {
         this.cfg = cfg;
         this.blockToNodesMap = blockToNodesMap;
         this.codeEmittingOrder = codeEmittingOrder;
@@ -99,7 +100,7 @@
     /**
      * Gets the nodes in a given block.
      */
-    public List<Node> nodesFor(Block block) {
+    public List<ScheduledNode> nodesFor(Block block) {
         return blockToNodesMap.get(block);
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Thu Jun 14 18:03:43 2012 +0200
@@ -106,22 +106,22 @@
      */
     public enum OperandFlag {
         /**
-         * The value can be a {@link CiRegisterValue}.
+         * The value can be a {@link RegisterValue}.
          */
         Register,
 
         /**
-         * The value can be a {@link CiStackSlot}.
+         * The value can be a {@link StackSlot}.
          */
         Stack,
 
         /**
-         * The value can be a {@link CiAddress}.
+         * The value can be a {@link Address}.
          */
         Address,
 
         /**
-         * The value can be a {@link CiConstant}.
+         * The value can be a {@link Constant}.
          */
         Constant,
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/Block.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/Block.java	Thu Jun 14 18:03:43 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
@@ -33,7 +32,7 @@
     protected int id;
 
     protected BeginNode beginNode;
-    protected Node endNode;
+    protected FixedNode endNode;
     protected Loop loop;
     protected double probability;
 
@@ -62,7 +61,7 @@
         return beginNode;
     }
 
-    public Node getEndNode() {
+    public FixedNode getEndNode() {
         return endNode;
     }
 
@@ -122,8 +121,8 @@
         return postdominator;
     }
 
-    private class NodeIterator implements Iterator<Node> {
-        private Node cur;
+    private class NodeIterator implements Iterator<FixedNode> {
+        private FixedNode cur;
 
         public NodeIterator() {
             cur = getBeginNode();
@@ -135,8 +134,8 @@
         }
 
         @Override
-        public Node next() {
-            Node result = cur;
+        public FixedNode next() {
+            FixedNode result = cur;
             if (cur == getEndNode()) {
                 cur = null;
             } else {
@@ -152,10 +151,10 @@
         }
     }
 
-    public Iterable<Node> getNodes() {
-        return new Iterable<Node>() {
+    public Iterable<FixedNode> getNodes() {
+        return new Iterable<FixedNode>() {
             @Override
-            public Iterator<Node> iterator() {
+            public Iterator<FixedNode> iterator() {
                 return new NodeIterator();
             }
         };
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/ControlFlowGraph.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/ControlFlowGraph.java	Thu Jun 14 18:03:43 2012 +0200
@@ -118,9 +118,9 @@
 
                 block.beginNode = (BeginNode) node;
                 Node cur = node;
+                Node last;
                 do {
                     assert !cur.isDeleted();
-                    block.endNode = cur;
 
                     assert nodeToBlock.get(cur) == null;
                     nodeToBlock.set(cur, block);
@@ -137,15 +137,11 @@
                         }
                     }
 
-                    Node next = null;
-                    for (Node sux : cur.successors()) {
-                        if (sux != null && !(sux instanceof BeginNode)) {
-                            assert next == null;
-                            next = sux;
-                        }
-                    }
-                    cur = next;
-                } while (cur != null);
+                    last = cur;
+                    cur = cur.successors().first();
+                } while (cur != null && !(cur instanceof BeginNode));
+
+                block.endNode = (FixedNode) last;
             }
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.nodes.type.*;
 
 public abstract class CallTargetNode extends ValueNode implements LIRLowerable {
+
     @Input protected final NodeInputList<ValueNode> arguments;
 
     public CallTargetNode(ValueNode[] arguments) {
@@ -45,6 +46,6 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        //nop
+        // nop
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -65,7 +65,7 @@
         return usages().filter(NodePredicates.isNotA(FrameState.class)).isEmpty();
     }
 
-    public static ConstantNode forCiConstant(Constant constant, CodeCacheProvider runtime, Graph graph) {
+    public static ConstantNode forConstant(Constant constant, CodeCacheProvider runtime, Graph graph) {
         if (constant.kind == Kind.Object) {
             return graph.unique(new ConstantNode(constant, runtime));
         } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Thu Jun 14 18:03:43 2012 +0200
@@ -35,7 +35,7 @@
  * The {@code FrameState} class encapsulates the frame state (i.e. local variables and
  * operand stack) at a particular point in the abstract interpretation.
  */
-public final class FrameState extends Node implements Node.IterableNodeType, LIRLowerable {
+public final class FrameState extends VirtualState implements Node.IterableNodeType, LIRLowerable {
 
     protected final int localsSize;
 
@@ -74,11 +74,10 @@
 
     @Input private final NodeInputList<ValueNode> values;
 
-    @Input private final NodeInputList<Node> virtualObjectMappings;
+    @Input private final NodeInputList<VirtualObjectState> virtualObjectMappings;
 
     /**
-     * The bytecode index to which this frame state applies. This will be {@code -1}
-     * iff this state is mutable.
+     * The bytecode index to which this frame state applies.
      */
     public final int bci;
 
@@ -93,19 +92,28 @@
      * @param stackSize size of the stack
      * @param rethrowException if true the VM should re-throw the exception on top of the stack when deopt'ing using this framestate
      */
-    public FrameState(ResolvedJavaMethod method, int bci, int localsSize, int stackSize, boolean rethrowException, boolean duringCall) {
+    public FrameState(ResolvedJavaMethod method, int bci, List<ValueNode> values, int stackSize, boolean rethrowException, boolean duringCall, List<VirtualObjectState> virtualObjectMappings) {
         assert stackSize >= 0;
+        assert (bci >= 0 && method != null) || (bci < 0 && method == null && values.isEmpty());
         this.method = method;
         this.bci = bci;
-        this.localsSize = localsSize;
+        this.localsSize = values.size() - stackSize;
         this.stackSize = stackSize;
-        this.values = new NodeInputList<>(this, localsSize + stackSize);
-        this.virtualObjectMappings = new NodeInputList<>(this);
+        this.values = new NodeInputList<>(this, values);
+        this.virtualObjectMappings = new NodeInputList<>(this, virtualObjectMappings);
         this.rethrowException = rethrowException;
         this.duringCall = duringCall;
         assert !rethrowException || stackSize == 1 : "must have exception on top of the stack";
     }
 
+    /**
+     * Simple constructor used to create marker FrameStates.
+     * @param bci marker bci, needs to be < 0
+     */
+    public FrameState(int bci) {
+        this(null, bci, Collections.<ValueNode>emptyList(), 0, false, false, Collections.<VirtualObjectState>emptyList());
+    }
+
     public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, ValueNode[] stack, int stackSize, boolean rethrowException, boolean duringCall) {
         this.method = method;
         this.bci = bci;
@@ -140,10 +148,6 @@
         this.outerFrameState = x;
     }
 
-    private void setValueAt(int i, ValueNode x) {
-        values.set(i, x);
-    }
-
     public boolean rethrowException() {
         return rethrowException;
     }
@@ -160,8 +164,7 @@
         return method;
     }
 
-    public void addVirtualObjectMapping(Node virtualObject) {
-        assert virtualObject instanceof VirtualObjectFieldNode || virtualObject instanceof PhiNode || virtualObject instanceof ValueProxyNode : virtualObject;
+    public void addVirtualObjectMapping(VirtualObjectState virtualObject) {
         virtualObjectMappings.add(virtualObject);
     }
 
@@ -173,7 +176,7 @@
         return virtualObjectMappings.get(i);
     }
 
-    public Iterable<Node> virtualObjectMappings() {
+    public Iterable<VirtualObjectState> virtualObjectMappings() {
         return virtualObjectMappings;
     }
 
@@ -192,9 +195,7 @@
     }
 
     public FrameState duplicate(int newBci, boolean duplicateOuter) {
-        FrameState other = graph().add(new FrameState(method, newBci, localsSize, stackSize, rethrowException, duringCall));
-        other.values.setAll(values);
-        other.virtualObjectMappings.setAll(virtualObjectMappings);
+        FrameState other = graph().add(new FrameState(method, newBci, values, stackSize, rethrowException, duringCall, virtualObjectMappings));
         FrameState newOuterFrameState = outerFrameState();
         if (duplicateOuter && newOuterFrameState != null) {
             newOuterFrameState = newOuterFrameState.duplicate(newOuterFrameState.bci, duplicateOuter);
@@ -209,29 +210,18 @@
      * or double is followed by a null slot.
      */
     public FrameState duplicateModified(int newBci, boolean newRethrowException, Kind popKind, ValueNode... pushedValues) {
-        int popSlots = 0;
+        ArrayList<ValueNode> copy = new ArrayList<>(values);
         if (popKind != Kind.Void) {
             if (stackAt(stackSize() - 1) == null) {
-                popSlots = 2;
-            } else {
-                popSlots = 1;
+                copy.remove(copy.size() - 1);
             }
-            assert stackAt(stackSize() - popSlots).kind().stackKind() == popKind.stackKind() || (stackAt(stackSize() - popSlots) instanceof BoxedVirtualObjectNode && popKind.isObject());
+            ValueNode lastSlot = copy.get(copy.size() - 1);
+            assert lastSlot.kind().stackKind() == popKind.stackKind() || (lastSlot instanceof BoxedVirtualObjectNode && popKind.isObject());
+            copy.remove(copy.size() - 1);
         }
+        Collections.addAll(copy, pushedValues);
 
-        int pushSlots = pushedValues.length;
-        FrameState other = graph().add(new FrameState(method, newBci, localsSize, stackSize - popSlots + pushSlots, newRethrowException, false));
-        for (int i = 0; i < localsSize; i++) {
-            other.setValueAt(i, localAt(i));
-        }
-        for (int i = 0; i < stackSize - popSlots; i++) {
-            other.setValueAt(localsSize + i, stackAt(i));
-        }
-        int slot = localsSize + stackSize - popSlots;
-        for (int i = 0; i < pushSlots; i++) {
-            other.setValueAt(slot++, pushedValues[i]);
-        }
-        other.virtualObjectMappings.setAll(virtualObjectMappings);
+        FrameState other = graph().add(new FrameState(method, newBci, copy, copy.size() - localsSize, newRethrowException, false, virtualObjectMappings));
         other.setOuterFrameState(outerFrameState());
         return other;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -135,6 +135,7 @@
 
     @Override
     public void intrinsify(Node node) {
+        assert !(node instanceof ValueNode) || ((ValueNode) node).kind().isVoid() == kind().isVoid();
         MethodCallTargetNode call = callTarget;
         FrameState stateAfter = stateAfter();
         if (node instanceof StateSplit) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -175,6 +175,7 @@
 
     @Override
     public void intrinsify(Node node) {
+        assert !(node instanceof ValueNode) || ((ValueNode) node).kind().isVoid() == kind().isVoid();
         MethodCallTargetNode call = callTarget;
         FrameState state = stateAfter();
         killExceptionEdge();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -36,8 +36,7 @@
 
     public static enum PhiType {
         Value(null), // normal value phis
-        Memory(StampFactory.dependency()), // memory phis
-        Virtual(StampFactory.virtual()); // phis used for VirtualObjectField merges
+        Memory(StampFactory.dependency());
 
         public final Stamp stamp;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.graph.*;
 
-public class ScheduledNode extends Node {
+public abstract class ScheduledNode extends Node {
 
     @Successor private ScheduledNode scheduledNext; // the immediate successor of the current node
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java	Thu Jun 14 18:03:43 2012 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.graph.*;
+
+/**
+ * Base class for nodes that contain "virtual" state, like FrameState and VirtualObjectState.
+ * Subclasses of this class will be treated in a special way by the scheduler.
+ */
+public abstract class VirtualState extends Node {
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -68,7 +68,7 @@
                 Kind kind = location().kind();
                 Constant constant = kind.readUnsafeConstant(value, displacement);
                 if (constant != null) {
-                    return ConstantNode.forCiConstant(constant, runtime, graph());
+                    return ConstantNode.forConstant(constant, runtime, graph());
                 }
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -67,7 +67,7 @@
             }
 
             if (exactType != null) {
-                return ConstantNode.forCiConstant(exactType.getEncoding(Representation.ObjectHub), runtime, graph());
+                return ConstantNode.forConstant(exactType.getEncoding(Representation.ObjectHub), runtime, graph());
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -51,7 +51,7 @@
                 Kind kind = location().kind();
                 Constant constant = kind.readUnsafeConstant(value, displacement);
                 if (constant != null) {
-                    return ConstantNode.forCiConstant(constant, runtime, graph());
+                    return ConstantNode.forConstant(constant, runtime, graph());
                 }
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -39,13 +39,14 @@
         this(call, new ValueNode[0]);
     }
 
-    public RuntimeCallNode(RuntimeCall call, ValueNode arg1) {
-        this(call, new ValueNode[] {arg1});
+    public RuntimeCallNode(RuntimeCall call, ValueNode... arguments) {
+        super(StampFactory.forKind(call.resultKind), arguments);
+        this.call = call;
     }
 
-    public RuntimeCallNode(RuntimeCall call, ValueNode[] arguments) {
-        super(StampFactory.forKind(call.resultKind), arguments);
-        this.call = call;
+    @Override
+    public boolean hasSideEffect() {
+        return call.hasSideEffect();
     }
 
     @Override
@@ -53,16 +54,24 @@
         gen.emitRuntimeCall(this);
     }
 
+    @Override
+    public String toString(Verbosity verbosity) {
+        if (verbosity == Verbosity.Name) {
+            return super.toString(verbosity) + "#" + call;
+        }
+        return super.toString(verbosity);
+    }
+
     // specialized on return type (instead of public static <T> T performCall) until boxing/unboxing is sorted out in intrinsification
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static <S> double performCall(@ConstantNodeParameter RuntimeCall call, S arg1) {
+    public static <S> double callDouble(@ConstantNodeParameter RuntimeCall call, S arg1) {
         throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler");
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static long performCall(@ConstantNodeParameter RuntimeCall call) {
+    public static long callLong(@ConstantNodeParameter RuntimeCall call) {
         throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler");
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -34,11 +34,10 @@
 /**
  * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph.
  */
-
 public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType {
 
     public ValueAnchorNode(ValueNode... values) {
-        super(StampFactory.dependency(), values);
+        super(StampFactory.forVoid(), values);
     }
 
     @Override
@@ -53,6 +52,12 @@
     }
 
     @Override
+    public boolean verify() {
+        assertTrue(usages().isEmpty(), "upwards dependencies should target BeginNodes only");
+        return super.verify();
+    }
+
+    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (this.predecessor() instanceof ValueAnchorNode) {
             // transfer values and remove
@@ -69,7 +74,7 @@
             if (node instanceof IntegerDivNode || node instanceof IntegerRemNode) {
                 ArithmeticNode arithmeticNode = (ArithmeticNode) node;
                 if (arithmeticNode.y().isConstant()) {
-                    Constant  constant = arithmeticNode.y().asConstant();
+                    Constant constant = arithmeticNode.y().asConstant();
                     assert constant.kind == arithmeticNode.kind() : constant.kind + " != " + arithmeticNode.kind();
                     if (constant.asLong() != 0) {
                         continue;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -64,7 +64,7 @@
                 constant = field().constantValue(object().asConstant());
             }
             if (constant != null) {
-                return ConstantNode.forCiConstant(constant, runtime, graph());
+                return ConstantNode.forConstant(constant, runtime, graph());
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -70,7 +70,7 @@
                 Object array = arrayConst.asObject();
                 int length = Array.getLength(array);
                 if (index >= 0 && index < length) {
-                    return ConstantNode.forCiConstant(elementKind().readUnsafeConstant(array,
+                    return ConstantNode.forConstant(elementKind().readUnsafeConstant(array,
                                     elementKind().arrayBaseOffset() + index * elementKind().arrayIndexScale()), runtime, graph());
                 }
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java	Thu Jun 14 18:03:43 2012 +0200
@@ -29,8 +29,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.virtual.*;
-
 
 public abstract class EscapeOp {
 
@@ -43,7 +41,7 @@
         } else if (usage instanceof IsTypeNode) {
             assert ((IsTypeNode) usage).objectClass() == node;
             return false;
-        } else if (usage instanceof FrameState) {
+        } else if (usage instanceof VirtualState) {
             assert usage.inputs().contains(node);
             return true;
         } else if (usage instanceof AccessMonitorNode) {
@@ -73,8 +71,6 @@
                 // in order to not escape the access needs to have a valid constant index and either a store into node or self-referencing
                 return !isValidConstantIndex(x) || x.value() == node && x.array() != node;
             }
-        } else if (usage instanceof VirtualObjectFieldNode) {
-            return false;
         } else if (usage instanceof RegisterFinalizerNode) {
             assert ((RegisterFinalizerNode) usage).object() == node;
             return false;
@@ -112,8 +108,8 @@
             ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(false, node.graph()));
         } else if (usage instanceof IsTypeNode) {
             IsTypeNode x = (IsTypeNode) usage;
-            assert x.type() == ((ValueNode) node).objectStamp().type();
-            ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(true, node.graph()));
+            boolean result = ((ValueNode) node).objectStamp().type() == x.type();
+            ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(result, node.graph()));
         } else if (usage instanceof AccessMonitorNode) {
             ((AccessMonitorNode) usage).eliminate();
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Thu Jun 14 18:03:43 2012 +0200
@@ -31,14 +31,12 @@
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.iterators.NodePredicates.PositiveTypePredicate;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.virtual.*;
 
 public class GraphUtil {
 
-    private static final PositiveTypePredicate FLOATING = isA(FloatingNode.class).or(CallTargetNode.class).or(FrameState.class).or(VirtualObjectFieldNode.class).or(VirtualObjectNode.class);
+    private static final PositiveTypePredicate FLOATING = isA(FloatingNode.class).or(VirtualState.class).or(CallTargetNode.class);
 
     public static void killCFG(FixedNode node) {
         assert node.isAlive();
@@ -61,30 +59,32 @@
 
     private static void killEnd(EndNode end) {
         MergeNode merge = end.merge();
-        merge.removeEnd(end);
-        StructuredGraph graph = (StructuredGraph) end.graph();
-        if (merge instanceof LoopBeginNode && merge.forwardEndCount() == 0) { //dead loop
-            for (PhiNode phi : merge.phis().snapshot()) {
-                propagateKill(phi);
-            }
-            LoopBeginNode begin = (LoopBeginNode) merge;
-            // disconnect and delete loop ends & loop exits
-            for (LoopEndNode loopend : begin.loopEnds().snapshot()) {
-                loopend.predecessor().replaceFirstSuccessor(loopend, null);
-                loopend.safeDelete();
+        if (merge != null) {
+            merge.removeEnd(end);
+            StructuredGraph graph = (StructuredGraph) end.graph();
+            if (merge instanceof LoopBeginNode && merge.forwardEndCount() == 0) { //dead loop
+                for (PhiNode phi : merge.phis().snapshot()) {
+                    propagateKill(phi);
+                }
+                LoopBeginNode begin = (LoopBeginNode) merge;
+                // disconnect and delete loop ends & loop exits
+                for (LoopEndNode loopend : begin.loopEnds().snapshot()) {
+                    loopend.predecessor().replaceFirstSuccessor(loopend, null);
+                    loopend.safeDelete();
+                }
+                for (LoopExitNode loopexit : begin.loopExits().snapshot()) {
+                    for (ValueProxyNode vpn : loopexit.proxies().snapshot()) {
+                        graph.replaceFloating(vpn, vpn.value());
+                    }
+                    graph.replaceFixedWithFixed(loopexit, graph.add(new BeginNode()));
+                }
+                killCFG(begin.next());
+                begin.safeDelete();
+            } else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) { // not a loop anymore
+                graph.reduceDegenerateLoopBegin((LoopBeginNode) merge);
+            } else if (merge.phiPredecessorCount() == 1) { // not a merge anymore
+                graph.reduceTrivialMerge(merge);
             }
-            for (LoopExitNode loopexit : begin.loopExits().snapshot()) {
-                for (ValueProxyNode vpn : loopexit.proxies().snapshot()) {
-                    graph.replaceFloating(vpn, vpn.value());
-                }
-                graph.replaceFixedWithFixed(loopexit, graph.add(new BeginNode()));
-            }
-            killCFG(begin.next());
-            begin.safeDelete();
-        } else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) { // not a loop anymore
-            graph.reduceDegenerateLoopBegin((LoopBeginNode) merge);
-        } else if (merge.phiPredecessorCount() == 1) { // not a merge anymore
-            graph.reduceTrivialMerge(merge);
         }
     }
 
@@ -219,144 +219,4 @@
         }
         return v;
     }
-
-    private static ValueProxyNode findProxy(ValueNode value, BeginNode proxyPoint) {
-        for (ValueProxyNode vpn : proxyPoint.proxies()) {
-            ValueNode v = vpn;
-            while (v instanceof ValueProxyNode) {
-                v = ((ValueProxyNode) v).value();
-                if (v == value) {
-                    return vpn;
-                }
-            }
-        }
-        return null;
-    }
-
-    public static ValueNode mergeVirtualChain(
-                    StructuredGraph graph,
-                    ValueNode vof,
-                    ValueNode newVof,
-                    PhiNode vPhi,
-                    BeginNode earlyExit,
-                    BeginNode newEarlyExit,
-                    MergeNode merge) {
-        VirtualObjectNode vObject = virtualObject(vof);
-        assert virtualObject(newVof) == vObject;
-        ValueNode[] virtualState = virtualState(vof);
-        ValueNode[] newVirtualState = virtualState(newVof);
-        ValueNode chain = vPhi;
-        for (int i = 0; i < virtualState.length; i++) {
-            ValueNode value = virtualState[i];
-            ValueNode newValue = newVirtualState[i];
-            assert value.kind() == newValue.kind();
-            if (value != newValue) {
-                PhiNode valuePhi = graph.add(new PhiNode(value.kind(), merge));
-                ValueProxyNode inputProxy = findProxy(value, earlyExit);
-                if (inputProxy != null) {
-                    ValueProxyNode newInputProxy = findProxy(newValue, newEarlyExit);
-                    assert newInputProxy != null : "no proxy for " + newValue + " at " + newEarlyExit;
-                    valuePhi.addInput(inputProxy);
-                    valuePhi.addInput(newInputProxy);
-                } else {
-                    valuePhi.addInput(graph.unique(new ValueProxyNode(value, earlyExit, PhiType.Value)));
-                    valuePhi.addInput(newValue);
-                }
-                chain = graph.add(new VirtualObjectFieldNode(vObject, chain, valuePhi, i));
-            }
-        }
-        return chain;
-    }
-
-    public static ValueNode mergeVirtualChain(
-                    StructuredGraph graph,
-                    PhiNode vPhi,
-                    MergeNode merge) {
-        NodeInputList<ValueNode> virtuals = vPhi.values();
-        VirtualObjectNode vObject = virtualObject(unProxify(virtuals.first()));
-        List<ValueNode[]> virtualStates = new ArrayList<>(virtuals.size());
-        for (ValueNode virtual : virtuals) {
-            virtualStates.add(virtualState(unProxify(virtual)));
-        }
-        ValueNode chain = vPhi;
-        int stateLength = virtualStates.get(0).length;
-        for (int i = 0; i < stateLength; i++) {
-            ValueNode v = null;
-            boolean reconcile = false;
-            for (ValueNode[] state : virtualStates) {
-                if (v == null) {
-                    v = state[i];
-                } else if (v != state[i]) {
-                    reconcile = true;
-                    break;
-                }
-                assert v.kind() == state[i].kind();
-            }
-            if (reconcile) {
-                PhiNode valuePhi = graph.add(new PhiNode(v.kind(), merge));
-                for (ValueNode[] state : virtualStates) {
-                    valuePhi.addInput(state[i]);
-                }
-                chain = graph.add(new VirtualObjectFieldNode(vObject, chain, valuePhi, i));
-            }
-        }
-        return chain;
-    }
-
-    /**
-     * Returns the VirtualObjectNode associated with the virtual chain of the provided virtual node.
-     * @param vof a virtual ValueNode (a VirtualObjectFieldNode or a Virtual Phi)
-     * @return the VirtualObjectNode associated with the virtual chain of the provided virtual node.
-     */
-    public static VirtualObjectNode virtualObject(ValueNode vof) {
-        assert vof instanceof VirtualObjectFieldNode || (vof instanceof PhiNode && ((PhiNode) vof).type() == PhiType.Virtual) : vof;
-        ValueNode currentField = vof;
-        do {
-            if (currentField instanceof VirtualObjectFieldNode) {
-               return ((VirtualObjectFieldNode) currentField).object();
-            } else {
-                assert currentField instanceof PhiNode && ((PhiNode) currentField).type() == PhiType.Virtual : currentField;
-                currentField = ((PhiNode) currentField).valueAt(0);
-            }
-        } while (currentField != null);
-        throw new GraalInternalError("Invalid virtual chain : cound not find virtual object from %s", vof);
-    }
-
-    /**
-     * Builds the state of the virtual object at the provided point into a virtual chain.
-     * @param vof a virtual ValueNode (a VirtualObjectFieldNode or a Virtual Phi)
-     * @return the state of the virtual object at the provided point into a virtual chain.
-     */
-    public static ValueNode[] virtualState(ValueNode vof) {
-        return virtualState(vof, virtualObject(vof));
-    }
-
-    /**
-     * Builds the state of the virtual object at the provided point into a virtual chain.
-     * @param vof a virtual ValueNode (a VirtualObjectFieldNode or a Virtual Phi)
-     * @param vObj the virtual object
-     * @return the state of the virtual object at the provided point into a virtual chain.
-     */
-    public static ValueNode[] virtualState(ValueNode vof, VirtualObjectNode vObj) {
-        int fieldsCount = vObj.fieldsCount();
-        int dicovered = 0;
-        ValueNode[] state = new ValueNode[fieldsCount];
-        ValueNode currentField = vof;
-        do {
-            if (currentField instanceof VirtualObjectFieldNode) {
-                int index = ((VirtualObjectFieldNode) currentField).index();
-                if (state[index] == null) {
-                    dicovered++;
-                    state[index] = ((VirtualObjectFieldNode) currentField).input();
-                }
-                currentField = ((VirtualObjectFieldNode) currentField).lastState();
-            } else if (currentField instanceof ValueProxyNode) {
-                currentField = ((ValueProxyNode) currentField).value();
-            } else {
-                assert currentField instanceof PhiNode && ((PhiNode) currentField).type() == PhiType.Virtual : currentField;
-                currentField = ((PhiNode) currentField).valueAt(0);
-            }
-        } while (currentField != null && dicovered < fieldsCount);
-        return state;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * 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.nodes.virtual;
-
-import java.util.*;
-
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public class VirtualObjectFieldNode extends ValueNode implements LIRLowerable {
-
-    @Input private VirtualObjectNode object;
-    @Input private ValueNode lastState;
-    @Input private ValueNode input;
-
-    private int index;
-
-    public VirtualObjectNode object() {
-        return object;
-    }
-
-    public ValueNode lastState() {
-        return lastState;
-    }
-
-    public ValueNode input() {
-        return input;
-    }
-
-    public VirtualObjectFieldNode(VirtualObjectNode object, ValueNode lastState, ValueNode input, int index) {
-        super(StampFactory.virtual());
-        this.index = index;
-        this.object = object;
-        this.lastState = lastState;
-        this.input = input;
-    }
-
-    public int index() {
-        return index;
-    }
-
-    @Override
-    public void generate(LIRGeneratorTool gen) {
-        // nothing to do...
-    }
-
-    @Override
-    public boolean verify() {
-        assertTrue(object != null, "No object");
-        assertTrue(input != null, "No input");
-        return super.verify();
-    }
-
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
-        properties.put("index", index);
-        return properties;
-    }
-
-    @Override
-    public String toString(Verbosity verbosity) {
-        if (verbosity == Verbosity.Name && object() != null && object().fields() != null) {
-            return super.toString(Verbosity.Name) + " " + object().fields()[index].name();
-        } else {
-            return super.toString(verbosity);
-        }
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Thu Jun 14 18:03:43 2012 +0200
@@ -23,12 +23,11 @@
 package com.oracle.graal.nodes.virtual;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-
-public class VirtualObjectNode extends ValueNode implements LIRLowerable {
+public class VirtualObjectNode extends FloatingNode implements LIRLowerable {
 
     private ResolvedJavaType type;
     private EscapeField[] fields;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java	Thu Jun 14 18:03:43 2012 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.virtual;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * This class encapsulated the virtual state of an escape analyzed object.
+ */
+public final class VirtualObjectState extends VirtualState implements Node.IterableNodeType, LIRLowerable {
+
+    @Input private VirtualObjectNode object;
+    @Input private NodeInputList<ValueNode> fields;
+
+    public VirtualObjectNode object() {
+        return object;
+    }
+
+    public NodeInputList<ValueNode> fields() {
+        return fields;
+    }
+
+    public VirtualObjectState(VirtualObjectNode object, ValueNode[] fields) {
+        this.object = object;
+        assert object.fields().length == fields.length;
+        this.fields = new NodeInputList<>(this, fields);
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool generator) {
+        // Nothing to do, virtual object states are processed as part of the handling of StateSplit nodes.
+    }
+}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java	Thu Jun 14 18:03:43 2012 +0200
@@ -22,20 +22,18 @@
  */
 package com.oracle.graal.snippets;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.cri.*;
 
 /**
  * Definition of the snippets that are VM-independent and can be intrinsified by Graal in any VM.
  */
 public class GraalIntrinsics {
-    public static void installIntrinsics(ExtendedRiRuntime runtime, TargetDescription target) {
+    public static void installIntrinsics(SnippetInstaller installer) {
         if (GraalOptions.Intrinsify) {
-            Snippets.install(runtime, target, new MathSnippetsX86());
-            Snippets.install(runtime, target, new DoubleSnippets());
-            Snippets.install(runtime, target, new FloatSnippets());
-            Snippets.install(runtime, target, new NodeClassSnippets());
+            installer.install(MathSnippetsX86.class);
+            installer.install(DoubleSnippets.class);
+            installer.install(FloatSnippets.class);
+            installer.install(NodeClassSnippets.class);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java	Thu Jun 14 18:03:43 2012 +0200
@@ -0,0 +1,163 @@
+/*
+ * 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.snippets;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * Provides printf-like debug facility. This should only be used in {@linkplain Snippet snippets}.
+ */
+public final class Log {
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic(RuntimeCallNode.class)
+    private static void log(@ConstantNodeParameter RuntimeCall logObject, Object object, boolean newline, boolean string) {
+        throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler");
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic(RuntimeCallNode.class)
+    private static void log(@ConstantNodeParameter RuntimeCall logPrimitive, int typeChar, long value, boolean newline) {
+        throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler");
+    }
+
+    public static void print(boolean value) {
+        log(RuntimeCall.LogPrimitive, Kind.Boolean.typeChar, value ? 1L : 0L, false);
+    }
+
+    public static void print(byte value) {
+        log(RuntimeCall.LogPrimitive, Kind.Byte.typeChar, value, false);
+    }
+
+    public static void print(char value) {
+        log(RuntimeCall.LogPrimitive, Kind.Char.typeChar, value, false);
+    }
+
+    public static void print(short value) {
+        log(RuntimeCall.LogPrimitive, Kind.Short.typeChar, value, false);
+    }
+
+    public static void print(int value) {
+        log(RuntimeCall.LogPrimitive, Kind.Int.typeChar, value, false);
+    }
+
+    public static void print(long value) {
+        log(RuntimeCall.LogPrimitive, Kind.Long.typeChar, value, false);
+    }
+
+    public static void print(float value) {
+        if (Float.isNaN(value)) {
+            print("NaN");
+        } else if (value == Float.POSITIVE_INFINITY) {
+            print("Infinity");
+        } else if (value == Float.NEGATIVE_INFINITY) {
+            print("-Infinity");
+        } else {
+            log(RuntimeCall.LogPrimitive, Kind.Float.typeChar, Float.floatToRawIntBits(value), false);
+        }
+    }
+
+    public static void print(double value) {
+        if (Double.isNaN(value)) {
+            print("NaN");
+        } else if (value == Double.POSITIVE_INFINITY) {
+            print("Infinity");
+        } else if (value == Double.NEGATIVE_INFINITY) {
+            print("-Infinity");
+        } else {
+            log(RuntimeCall.LogPrimitive, Kind.Double.typeChar, Double.doubleToRawLongBits(value), false);
+        }
+    }
+
+    public static void print(String value) {
+        log(RuntimeCall.LogObject, value, false, true);
+    }
+
+    public static void printAddress(Object o) {
+        log(RuntimeCall.LogObject, o, false, false);
+    }
+
+    public static void println(boolean value) {
+        log(RuntimeCall.LogPrimitive, Kind.Boolean.typeChar, value ? 1L : 0L, true);
+    }
+
+    public static void println(byte value) {
+        log(RuntimeCall.LogPrimitive, Kind.Byte.typeChar, value, true);
+    }
+
+    public static void println(char value) {
+        log(RuntimeCall.LogPrimitive, Kind.Char.typeChar, value, true);
+    }
+
+    public static void println(short value) {
+        log(RuntimeCall.LogPrimitive, Kind.Short.typeChar, value, true);
+    }
+
+    public static void println(int value) {
+        log(RuntimeCall.LogPrimitive, Kind.Int.typeChar, value, true);
+    }
+
+    public static void println(long value) {
+        log(RuntimeCall.LogPrimitive, Kind.Long.typeChar, value, true);
+    }
+
+    public static void println(float value) {
+        if (Float.isNaN(value)) {
+            println("NaN");
+        } else if (value == Float.POSITIVE_INFINITY) {
+            println("Infinity");
+        } else if (value == Float.NEGATIVE_INFINITY) {
+            println("-Infinity");
+        } else {
+            log(RuntimeCall.LogPrimitive, Kind.Float.typeChar, Float.floatToRawIntBits(value), true);
+        }
+    }
+
+    public static void println(double value) {
+        if (Double.isNaN(value)) {
+            println("NaN");
+        } else if (value == Double.POSITIVE_INFINITY) {
+            println("Infinity");
+        } else if (value == Double.NEGATIVE_INFINITY) {
+            println("-Infinity");
+        } else {
+            log(RuntimeCall.LogPrimitive, Kind.Double.typeChar, Double.doubleToRawLongBits(value), true);
+        }
+    }
+
+    public static void println(String value) {
+        log(RuntimeCall.LogObject, value, true, true);
+    }
+
+    public static void printlnAddress(Object o) {
+        log(RuntimeCall.LogObject, o, true, false);
+    }
+
+    public static void println() {
+        println("");
+    }
+}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java	Thu Jun 14 18:03:43 2012 +0200
@@ -61,7 +61,7 @@
         if (abs(x) < PI_4) {
             return MathIntrinsicNode.compute(x, Operation.SIN);
         } else {
-            return RuntimeCallNode.performCall(RuntimeCall.ArithmeticSin, x);
+            return RuntimeCallNode.callDouble(RuntimeCall.ArithmeticSin, x);
         }
     }
 
@@ -69,7 +69,7 @@
         if (abs(x) < PI_4) {
             return MathIntrinsicNode.compute(x, Operation.COS);
         } else {
-            return RuntimeCallNode.performCall(RuntimeCall.ArithmeticCos, x);
+            return RuntimeCallNode.callDouble(RuntimeCall.ArithmeticCos, x);
         }
     }
 
@@ -77,7 +77,7 @@
         if (abs(x) < PI_4) {
             return MathIntrinsicNode.compute(x, Operation.TAN);
         } else {
-            return RuntimeCallNode.performCall(RuntimeCall.ArithmeticTan, x);
+            return RuntimeCallNode.callDouble(RuntimeCall.ArithmeticTan, x);
         }
     }
 
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java	Thu Jun 14 18:03:43 2012 +0200
@@ -25,6 +25,7 @@
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.snippets.nodes.*;
 
@@ -41,6 +42,50 @@
 public @interface Snippet {
 
     /**
+     * Specifies the class defining the inlining policy for this snippet.
+     * A {@linkplain InliningPolicy#Default default} policy is used if none is supplied.
+     */
+    Class<? extends InliningPolicy> inlining() default InliningPolicy.class;
+
+    /**
+     * Guides inlining decisions used when installing a snippet.
+     */
+    public interface InliningPolicy {
+        /**
+         * Determines if {@code method} should be inlined into {@code caller}.
+         */
+        boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller);
+
+        /**
+         * The default inlining policy which inlines everything except for
+         * constructors of {@link Throwable} classes.
+         */
+        InliningPolicy Default = new InliningPolicy() {
+            public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) {
+                if (Throwable.class.isAssignableFrom(method.holder().toJava())) {
+                    if (method.name().equals("<init>")) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+        };
+    }
+
+    /**
+     * Annotates a method replaced by a compile-time constant.
+     * A (resolved) call to the annotated method is replaced
+     * with a constant obtained by calling the annotated method via reflection.
+     *
+     * All arguments to such a method (including the receiver if applicable)
+     * must be compile-time constants.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    public static @interface Fold {
+    }
+
+    /**
      * Denotes a snippet parameter that will be bound during snippet
      * template {@linkplain SnippetTemplate#instantiate instantiation}.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Thu Jun 14 18:03:43 2012 +0200
@@ -0,0 +1,195 @@
+/*
+ * 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.snippets;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.compiler.util.*;
+import com.oracle.graal.cri.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.snippets.Snippet.InliningPolicy;
+
+/**
+ * Utility for snippet {@linkplain #install(Class) installation}.
+ */
+public class SnippetInstaller {
+
+    private final ExtendedRiRuntime runtime;
+    private final TargetDescription target;
+    private final BoxingMethodPool pool;
+
+    /**
+     * A graph cache used by this installer to avoid using the compiler
+     * storage for each method processed during snippet installation.
+     * Without this, all processed methods are to be determined as
+     * {@linkplain IntrinsificationPhase#canIntrinsify intrinsifiable}.
+     */
+    private final Map<ResolvedJavaMethod, StructuredGraph> graphCache;
+
+    public SnippetInstaller(ExtendedRiRuntime runtime, TargetDescription target) {
+        this.runtime = runtime;
+        this.target = target;
+        this.pool = new BoxingMethodPool(runtime);
+        this.graphCache = new HashMap<>();
+    }
+
+    /**
+     * Finds all the snippet methods in a given class, builds a graph for them and
+     * installs the graph with the key value of {@code Graph.class} in the
+     * {@linkplain ResolvedJavaMethod#compilerStorage() compiler storage} of each method.
+     * <p>
+     * If {@code snippetsHolder} is annotated with {@link ClassSubstitution}, then all
+     * methods in the class are snippets. Otherwise, the snippets are those methods
+     * annotated with {@link Snippet}.
+     */
+    public void install(Class<? extends SnippetsInterface> snippetsHolder) {
+        if (snippetsHolder.isAnnotationPresent(ClassSubstitution.class)) {
+            installSubstitutions(snippetsHolder, snippetsHolder.getAnnotation(ClassSubstitution.class).value());
+        } else {
+            installSnippets(snippetsHolder);
+        }
+    }
+
+    private void installSnippets(Class< ? extends SnippetsInterface> clazz) {
+        for (Method method : clazz.getDeclaredMethods()) {
+            if (method.getAnnotation(Snippet.class) != null) {
+                int modifiers = method.getModifiers();
+                if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
+                    throw new RuntimeException("Snippet must not be abstract or native");
+                }
+                ResolvedJavaMethod snippet = runtime.getResolvedJavaMethod(method);
+                assert snippet.compilerStorage().get(Graph.class) == null;
+                StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet));
+                //System.out.println("snippet: " + graph);
+                snippet.compilerStorage().put(Graph.class, graph);
+            }
+        }
+    }
+
+    private void installSubstitutions(Class< ? extends SnippetsInterface> clazz, Class<?> originalClazz) {
+        for (Method method : clazz.getDeclaredMethods()) {
+            try {
+                Method originalMethod = originalClazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
+                if (!originalMethod.getReturnType().isAssignableFrom(method.getReturnType())) {
+                    throw new RuntimeException("Snippet has incompatible return type");
+                }
+                int modifiers = method.getModifiers();
+                if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
+                    throw new RuntimeException("Snippet must not be abstract or native");
+                }
+                ResolvedJavaMethod snippet = runtime.getResolvedJavaMethod(method);
+                StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet));
+                //System.out.println("snippet: " + graph);
+                runtime.getResolvedJavaMethod(originalMethod).compilerStorage().put(Graph.class, graph);
+            } catch (NoSuchMethodException e) {
+                throw new GraalInternalError("Could not resolve method in " + originalClazz + " to substitute with " + method, e);
+            }
+        }
+    }
+
+    private static InliningPolicy inliningPolicy(ResolvedJavaMethod method) {
+        Class<? extends InliningPolicy> policyClass = InliningPolicy.class;
+        Snippet snippet = method.getAnnotation(Snippet.class);
+        if (snippet != null) {
+            policyClass = snippet.inlining();
+        }
+        if (policyClass == InliningPolicy.class) {
+            return InliningPolicy.Default;
+        }
+        try {
+            return policyClass.getConstructor().newInstance();
+        } catch (Exception e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
+    private StructuredGraph makeGraph(final ResolvedJavaMethod method, final InliningPolicy policy) {
+        StructuredGraph graph = graphCache.get(method);
+        if (graph == null) {
+            graph = buildGraph(method, policy);
+            //System.out.println("built " + graph);
+            graphCache.put(method, graph);
+        }
+        return graph;
+    }
+
+    private StructuredGraph buildGraph(final ResolvedJavaMethod method, final InliningPolicy policy) {
+        final StructuredGraph graph = new StructuredGraph(method);
+        return Debug.scope("BuildSnippetGraph", new Object[] {method, graph}, new Callable<StructuredGraph>() {
+            @Override
+            public StructuredGraph call() throws Exception {
+                GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault();
+                GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE);
+                graphBuilder.apply(graph);
+
+                Debug.dump(graph, "%s: %s", method.name(), GraphBuilderPhase.class.getSimpleName());
+
+                new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
+
+                for (Invoke invoke : graph.getInvokes()) {
+                    MethodCallTargetNode callTarget = invoke.callTarget();
+                    ResolvedJavaMethod callee = callTarget.targetMethod();
+                    if (policy.shouldInline(callee, method)) {
+                        StructuredGraph targetGraph = makeGraph(callee, policy);
+                        InliningUtil.inline(invoke, targetGraph, true);
+                        Debug.dump(graph, "after inlining %s", callee);
+                        if (GraalOptions.OptCanonicalizer) {
+                            new WordTypeRewriterPhase(target).apply(graph);
+                            new CanonicalizerPhase(target, runtime, null).apply(graph);
+                        }
+                    }
+                }
+
+                new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
+
+                new WordTypeRewriterPhase(target).apply(graph);
+
+                new DeadCodeEliminationPhase().apply(graph);
+                if (GraalOptions.OptCanonicalizer) {
+                    new CanonicalizerPhase(target, runtime, null).apply(graph);
+                }
+
+                for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
+                    end.disableSafepoint();
+                }
+
+                new InsertStateAfterPlaceholderPhase().apply(graph);
+
+                Debug.dump(graph, "%s: Final", method.name());
+
+                return graph;
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java	Thu Jun 14 18:03:43 2012 +0200
@@ -0,0 +1,353 @@
+/*
+ * 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.snippets;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.snippets.Snippet.Fold;
+
+public class SnippetIntrinsificationPhase extends Phase {
+
+    private final CodeCacheProvider runtime;
+    private final BoxingMethodPool pool;
+
+    public SnippetIntrinsificationPhase(CodeCacheProvider runtime, BoxingMethodPool pool) {
+        this.runtime = runtime;
+        this.pool = pool;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (Invoke i : graph.getInvokes()) {
+            tryIntrinsify(i);
+        }
+    }
+
+    private void tryIntrinsify(Invoke invoke) {
+        ResolvedJavaMethod target = invoke.callTarget().targetMethod();
+        NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class);
+        if (intrinsic != null) {
+            assert target.getAnnotation(Fold.class) == null;
+
+            Class< ? >[] parameterTypes = CodeUtil.signatureToTypes(target.signature(), target.holder());
+
+            // Prepare the arguments for the reflective constructor call on the node class.
+            Object[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false);
+
+            // Create the new node instance.
+            Class< ? > c = getNodeClass(target, intrinsic);
+            Node newInstance = createNodeInstance(c, parameterTypes, nodeConstructorArguments);
+
+            // Replace the invoke with the new node.
+            invoke.node().graph().add(newInstance);
+            invoke.intrinsify(newInstance);
+
+            // Clean up checkcast instructions inserted by javac if the return type is generic.
+            cleanUpReturnCheckCast(newInstance);
+        } else if (target.getAnnotation(Fold.class) != null) {
+            Class< ? >[] parameterTypes = CodeUtil.signatureToTypes(target.signature(), target.holder());
+
+            // Prepare the arguments for the reflective method call
+            Object[] arguments = prepareArguments(invoke, parameterTypes, target, true);
+            Object receiver = null;
+            if (!invoke.callTarget().isStatic()) {
+                receiver = arguments[0];
+                arguments = Arrays.asList(arguments).subList(1, arguments.length).toArray();
+            }
+
+            // Call the method
+            Constant constant = callMethod(target.signature().returnKind(), target.holder().toJava(), target.name(), parameterTypes, receiver, arguments);
+
+            if (constant != null) {
+                // Replace the invoke with the result of the call
+                ConstantNode node = ConstantNode.forConstant(constant, runtime, invoke.node().graph());
+                invoke.intrinsify(node);
+
+                // Clean up checkcast instructions inserted by javac if the return type is generic.
+                cleanUpReturnCheckCast(node);
+            } else {
+                // Remove the invoke
+                invoke.intrinsify(null);
+            }
+        }
+    }
+
+    /**
+     * Converts the arguments of an invoke node to object values suitable for use as the arguments
+     * to a reflective invocation of a Java constructor or method.
+     *
+     * @param folding specifies if the invocation is for handling a {@link Fold} annotation
+     */
+    private Object[] prepareArguments(Invoke invoke, Class< ? >[] parameterTypes, ResolvedJavaMethod target, boolean folding) {
+        NodeInputList<ValueNode> arguments = invoke.callTarget().arguments();
+        Object[] reflectionCallArguments = new Object[arguments.size()];
+        for (int i = 0; i < reflectionCallArguments.length; ++i) {
+            int parameterIndex = i;
+            if (!invoke.callTarget().isStatic()) {
+                parameterIndex--;
+            }
+            ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i));
+            if (folding || CodeUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) {
+                assert argument instanceof ConstantNode : "parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.callTarget().targetMethod() + ": " + argument;
+                ConstantNode constantNode = (ConstantNode) argument;
+                Constant constant = constantNode.asConstant();
+                Object o = constant.boxedValue();
+                if (o instanceof Class< ? >) {
+                    reflectionCallArguments[i] = runtime.getResolvedJavaType((Class< ? >) o);
+                    parameterTypes[i] = ResolvedJavaType.class;
+                } else {
+                    if (parameterTypes[i] == boolean.class) {
+                        reflectionCallArguments[i] = Boolean.valueOf(constant.asInt() != 0);
+                    } else if (parameterTypes[i] == byte.class) {
+                        reflectionCallArguments[i] = Byte.valueOf((byte) constant.asInt());
+                    } else if (parameterTypes[i] == short.class) {
+                        reflectionCallArguments[i] = Short.valueOf((short) constant.asInt());
+                    } else if (parameterTypes[i] == char.class) {
+                        reflectionCallArguments[i] = Character.valueOf((char) constant.asInt());
+                    } else {
+                        reflectionCallArguments[i] = o;
+                    }
+                }
+            } else {
+                reflectionCallArguments[i] = argument;
+                parameterTypes[i] = ValueNode.class;
+            }
+        }
+        return reflectionCallArguments;
+    }
+
+    private static Class< ? > getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) {
+        Class< ? > result = intrinsic.value();
+        if (result == NodeIntrinsic.class) {
+            result = target.holder().toJava();
+        }
+        assert Node.class.isAssignableFrom(result);
+        return result;
+    }
+
+    private ValueNode tryBoxingElimination(int parameterIndex, ResolvedJavaMethod target, ValueNode node) {
+        if (parameterIndex >= 0) {
+            Type type = target.getGenericParameterTypes()[parameterIndex];
+            if (type instanceof TypeVariable) {
+                TypeVariable typeVariable = (TypeVariable) type;
+                if (typeVariable.getBounds().length == 1) {
+                    Type boundType = typeVariable.getBounds()[0];
+                    if (boundType instanceof Class && ((Class) boundType).getSuperclass() == null) {
+                        // Unbound generic => try boxing elimination
+                        if (node.usages().size() == 2) {
+                            if (node instanceof Invoke) {
+                                Invoke invokeNode = (Invoke) node;
+                                MethodCallTargetNode callTarget = invokeNode.callTarget();
+                                if (pool.isBoxingMethod(callTarget.targetMethod())) {
+                                    FrameState stateAfter = invokeNode.stateAfter();
+                                    assert stateAfter.usages().size() == 1;
+                                    invokeNode.node().replaceAtUsages(null);
+                                    ValueNode result = callTarget.arguments().get(0);
+                                    StructuredGraph graph = (StructuredGraph) node.graph();
+                                    if (invokeNode instanceof InvokeWithExceptionNode) {
+                                        // Destroy exception edge & clear stateAfter.
+                                        InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
+
+                                        invokeWithExceptionNode.killExceptionEdge();
+                                        graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE);
+                                    } else {
+                                        graph.removeFixed((InvokeNode) invokeNode);
+                                    }
+                                    stateAfter.safeDelete();
+                                    GraphUtil.propagateKill(callTarget);
+                                    return result;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return node;
+    }
+
+    private static Class asBoxedType(Class type) {
+        if (!type.isPrimitive()) {
+            return type;
+        }
+
+        if (Boolean.TYPE == type) {
+            return Boolean.class;
+        }
+        if (Character.TYPE == type) {
+            return Character.class;
+        }
+        if (Byte.TYPE == type) {
+            return Byte.class;
+        }
+        if (Short.TYPE == type) {
+            return Short.class;
+        }
+        if (Integer.TYPE == type) {
+            return Integer.class;
+        }
+        if (Long.TYPE == type) {
+            return Long.class;
+        }
+        if (Float.TYPE == type) {
+            return Float.class;
+        }
+        assert Double.TYPE == type;
+        return Double.class;
+    }
+
+    static final int VARARGS = 0x00000080;
+
+    private static Node createNodeInstance(Class< ? > nodeClass, Class< ? >[] parameterTypes, Object[] nodeConstructorArguments) {
+        Object[] arguments = null;
+        Constructor< ? > constructor = null;
+        nextConstructor:
+        for (Constructor c : nodeClass.getDeclaredConstructors()) {
+            Class[] signature = c.getParameterTypes();
+            if ((c.getModifiers() & VARARGS) != 0) {
+                int fixedArgs = signature.length - 1;
+                if (parameterTypes.length < fixedArgs) {
+                    continue nextConstructor;
+                }
+
+                for (int i = 0; i < fixedArgs; i++) {
+                    if (!parameterTypes[i].equals(signature[i])) {
+                        continue nextConstructor;
+                    }
+                }
+
+                Class componentType = signature[fixedArgs].getComponentType();
+                assert componentType != null : "expected last parameter of varargs constructor " + c + " to be an array type";
+                Class boxedType = asBoxedType(componentType);
+                for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
+                    if (!boxedType.isInstance(nodeConstructorArguments[i])) {
+                        continue nextConstructor;
+                    }
+                }
+
+                arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1);
+                int varargsLength = nodeConstructorArguments.length - fixedArgs;
+                Object varargs = Array.newInstance(componentType, varargsLength);
+                for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
+                    Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i]);
+                }
+                arguments[fixedArgs] = varargs;
+                constructor = c;
+                break;
+            } else if (Arrays.equals(parameterTypes, signature)) {
+                arguments = nodeConstructorArguments;
+                constructor = c;
+                break;
+            }
+        }
+        if (constructor == null) {
+            throw new GraalInternalError("Could not find constructor in " + nodeClass + " compatible with signature " + Arrays.toString(parameterTypes));
+        }
+        constructor.setAccessible(true);
+        try {
+            return (ValueNode) constructor.newInstance(arguments);
+        } catch (Exception e) {
+            throw new RuntimeException(constructor + Arrays.toString(nodeConstructorArguments), e);
+        }
+    }
+
+    /**
+     * Calls a Java method via reflection.
+     */
+    private static Constant callMethod(Kind returnKind, Class< ? > holder, String name, Class< ? >[] parameterTypes, Object receiver, Object[] arguments) {
+        Method method;
+        try {
+            method = holder.getDeclaredMethod(name, parameterTypes);
+            method.setAccessible(true);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        try {
+            Object result = method.invoke(receiver, arguments);
+            if (result == null) {
+                return null;
+            }
+            return Constant.forBoxed(returnKind, result);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static String sourceLocation(Node n) {
+        String loc = GraphUtil.approxSourceLocation(n);
+        return loc == null ? "<unknown>" : loc;
+    }
+
+    public void cleanUpReturnCheckCast(Node newInstance) {
+        if (newInstance instanceof ValueNode && ((ValueNode) newInstance).kind() != Kind.Object) {
+            StructuredGraph graph = (StructuredGraph) newInstance.graph();
+            for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) {
+                for (ValueProxyNode vpn : checkCastNode.usages().filter(ValueProxyNode.class).snapshot()) {
+                    graph.replaceFloating(vpn, checkCastNode);
+                }
+                for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
+                    if (checkCastUsage instanceof ValueAnchorNode) {
+                        ValueAnchorNode valueAnchorNode = (ValueAnchorNode) checkCastUsage;
+                        graph.removeFixed(valueAnchorNode);
+                    } else if (checkCastUsage instanceof MethodCallTargetNode) {
+                        MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage;
+                        assert pool.isUnboxingMethod(checkCastCallTarget.targetMethod()) :
+                            "checkcast at " + sourceLocation(checkCastNode) + " not used by an unboxing method but by a call at " +
+                            sourceLocation(checkCastCallTarget.usages().first()) + " to " + checkCastCallTarget.targetMethod();
+                        Invoke invokeNode = checkCastCallTarget.invoke();
+                        invokeNode.node().replaceAtUsages(newInstance);
+                        if (invokeNode instanceof InvokeWithExceptionNode) {
+                            // Destroy exception edge & clear stateAfter.
+                            InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
+
+                            invokeWithExceptionNode.killExceptionEdge();
+                            graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE);
+                        } else {
+                            graph.removeFixed((InvokeNode) invokeNode);
+                        }
+                        checkCastCallTarget.safeDelete();
+                    } else if (checkCastUsage instanceof FrameState) {
+                        checkCastUsage.replaceFirstInput(checkCastNode, null);
+                    } else {
+                        assert false : sourceLocation(checkCastUsage) + " has unexpected usage " + checkCastUsage + " of checkcast at " + sourceLocation(checkCastNode);
+                    }
+                }
+                FixedNode next = checkCastNode.next();
+                checkCastNode.setNext(null);
+                checkCastNode.replaceAtPredecessor(next);
+                GraphUtil.killCFG(checkCastNode);
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Thu Jun 14 18:03:43 2012 +0200
@@ -68,10 +68,12 @@
         }
 
         public Key add(String name, Object value) {
-            assert value != null;
             assert !map.containsKey(name);
             map.put(name, value);
-            hash = hash ^ name.hashCode() * (value.hashCode() + 1);
+            hash = hash ^ name.hashCode();
+            if (value != null) {
+                hash *= (value.hashCode() + 1);
+            }
             return this;
         }
 
@@ -194,10 +196,9 @@
             if (c != null) {
                 String name = c.value();
                 Object arg = key.get(name);
-                assert arg != null : method + ": requires a constant named " + name;
                 Kind kind = signature.argumentKindAt(i);
                 assert checkConstantArgument(method, signature, i, name, arg, kind);
-                replacements.put(snippetGraph.getLocal(i), ConstantNode.forCiConstant(Constant.forBoxed(kind, arg), runtime, snippetCopy));
+                replacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(Constant.forBoxed(kind, arg), runtime, snippetCopy));
             } else {
                 Parameter p = CodeUtil.getParameterAnnotation(Parameter.class, i, method);
                 assert p != null : method + ": parameter " + i + " must be annotated with either @Constant or @Parameter";
@@ -327,11 +328,11 @@
     private static boolean checkConstantArgument(final ResolvedJavaMethod method, Signature signature, int i, String name, Object arg, Kind kind) {
         if (kind.isObject()) {
             Class<?> type = signature.argumentTypeAt(i, method.holder()).resolve(method.holder()).toJava();
-            assert type.isInstance(arg) :
+            assert arg == null || type.isInstance(arg) :
                 method + ": wrong value type for " + name + ": expected " + type.getName() + ", got " + arg.getClass().getName();
         } else {
-            assert kind.toBoxedJavaClass() == arg.getClass() :
-                method + ": wrong value kind for " + name + ": expected " + kind + ", got " + arg.getClass().getSimpleName();
+            assert arg != null && kind.toBoxedJavaClass() == arg.getClass() :
+                method + ": wrong value kind for " + name + ": expected " + kind + ", got " + (arg == null ? "null" : arg.getClass().getSimpleName());
         }
         return true;
     }
@@ -386,7 +387,7 @@
                 } else {
                     Kind kind = ((LocalNode) parameter).kind();
                     Constant constant = Constant.forBoxed(kind, argument);
-                    replacements.put((LocalNode) parameter, ConstantNode.forCiConstant(constant, runtime, replaceeGraph));
+                    replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph));
                 }
             } else {
                 assert parameter instanceof LocalNode[];
@@ -399,7 +400,7 @@
                     LocalNode local = locals[j];
                     assert local != null;
                     Constant constant = Constant.forBoxed(local.kind(), Array.get(array, j));
-                    ConstantNode element = ConstantNode.forCiConstant(constant, runtime, replaceeGraph);
+                    ConstantNode element = ConstantNode.forConstant(constant, runtime, replaceeGraph);
                     replacements.put(local, element);
                 }
             }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java	Thu Jun 14 18:03:18 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-/*
- * 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.snippets;
-
-import java.lang.reflect.*;
-import java.util.concurrent.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.util.*;
-import com.oracle.graal.cri.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.java.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-
-/**
- * Utilities for snippet installation and management.
- */
-public class Snippets {
-
-    public static void install(ExtendedRiRuntime runtime, TargetDescription target, SnippetsInterface obj) {
-        Class<? extends SnippetsInterface> clazz = obj.getClass();
-        BoxingMethodPool pool = new BoxingMethodPool(runtime);
-        if (clazz.isAnnotationPresent(ClassSubstitution.class)) {
-            installSubstitution(runtime, target, clazz, pool, clazz.getAnnotation(ClassSubstitution.class).value());
-        } else {
-            installSnippets(runtime, target, clazz, pool);
-        }
-    }
-
-    private static void installSnippets(ExtendedRiRuntime runtime, TargetDescription target, Class< ? extends SnippetsInterface> clazz, BoxingMethodPool pool) {
-        for (Method method : clazz.getDeclaredMethods()) {
-            if (method.getAnnotation(Snippet.class) != null) {
-                Method snippet = method;
-                int modifiers = snippet.getModifiers();
-                if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
-                    throw new RuntimeException("Snippet must not be abstract or native");
-                }
-                ResolvedJavaMethod snippetRiMethod = runtime.getResolvedJavaMethod(snippet);
-                if (snippetRiMethod.compilerStorage().get(Graph.class) == null) {
-                    buildSnippetGraph(snippetRiMethod, runtime, target, pool);
-                }
-            }
-        }
-    }
-
-    private static void installSubstitution(ExtendedRiRuntime runtime, TargetDescription target, Class< ? extends SnippetsInterface> clazz,
-                    BoxingMethodPool pool, Class<?> original) throws GraalInternalError {
-        for (Method snippet : clazz.getDeclaredMethods()) {
-            try {
-                Method method = original.getDeclaredMethod(snippet.getName(), snippet.getParameterTypes());
-                if (!method.getReturnType().isAssignableFrom(snippet.getReturnType())) {
-                    throw new RuntimeException("Snippet has incompatible return type");
-                }
-                int modifiers = snippet.getModifiers();
-                if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
-                    throw new RuntimeException("Snippet must not be abstract or native");
-                }
-                ResolvedJavaMethod snippetRiMethod = runtime.getResolvedJavaMethod(snippet);
-                StructuredGraph graph = buildSnippetGraph(snippetRiMethod, runtime, target, pool);
-                runtime.getResolvedJavaMethod(method).compilerStorage().put(Graph.class, graph);
-            } catch (NoSuchMethodException e) {
-                throw new RuntimeException("Could not resolve method to substitute with: " + snippet.getName(), e);
-            }
-        }
-    }
-
-    private static StructuredGraph buildSnippetGraph(final ResolvedJavaMethod snippetRiMethod, final ExtendedRiRuntime runtime, final TargetDescription target, final BoxingMethodPool pool) {
-        final StructuredGraph graph = new StructuredGraph(snippetRiMethod);
-        return Debug.scope("BuildSnippetGraph", new Object[] {snippetRiMethod, graph}, new Callable<StructuredGraph>() {
-            @Override
-            public StructuredGraph call() throws Exception {
-                GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault();
-                GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE);
-                graphBuilder.apply(graph);
-
-                Debug.dump(graph, "%s: %s", snippetRiMethod.name(), GraphBuilderPhase.class.getSimpleName());
-
-                new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
-
-                for (Invoke invoke : graph.getInvokes()) {
-                    MethodCallTargetNode callTarget = invoke.callTarget();
-                    ResolvedJavaMethod targetMethod = callTarget.targetMethod();
-                    ResolvedJavaType holder = targetMethod.holder();
-                    if (enclosedInSnippetsClass(holder)) {
-                        StructuredGraph targetGraph = (StructuredGraph) targetMethod.compilerStorage().get(Graph.class);
-                        if (targetGraph == null) {
-                            targetGraph = buildSnippetGraph(targetMethod, runtime, target, pool);
-                        }
-                        InliningUtil.inline(invoke, targetGraph, true);
-                        Debug.dump(graph, "after inlining %s", targetMethod);
-                        if (GraalOptions.OptCanonicalizer) {
-                            new WordTypeRewriterPhase(target).apply(graph);
-                            new CanonicalizerPhase(target, runtime, null).apply(graph);
-                        }
-                    }
-                }
-
-                new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
-
-                new WordTypeRewriterPhase(target).apply(graph);
-
-                new DeadCodeEliminationPhase().apply(graph);
-                if (GraalOptions.OptCanonicalizer) {
-                    new CanonicalizerPhase(target, runtime, null).apply(graph);
-                }
-
-                for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
-                    end.disableSafepoint();
-                }
-
-                new InsertStateAfterPlaceholderPhase().apply(graph);
-
-                Debug.dump(graph, "%s: Final", snippetRiMethod.name());
-
-                snippetRiMethod.compilerStorage().put(Graph.class, graph);
-
-                return graph;
-            }
-
-            private boolean enclosedInSnippetsClass(ResolvedJavaType holder) {
-                Class enclosingClass = holder.toJava();
-                while (enclosingClass != null) {
-                    if (SnippetsInterface.class.isAssignableFrom(enclosingClass)) {
-                        return true;
-                    }
-                    enclosingClass = enclosingClass.getEnclosingClass();
-                }
-                return false;
-            }
-        });
-
-    }
-}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java	Thu Jun 14 18:03:43 2012 +0200
@@ -147,6 +147,10 @@
 
     private static int compilationId = 0;
 
+    protected void assertEquals(Object expected, Object actual) {
+        Assert.assertEquals(expected, actual);
+    }
+
     protected void test(String name, Object... args) {
         Method method = getMethod(name);
         Object expect = null;
@@ -171,7 +175,7 @@
             }
         } else {
             Object actual = compiledMethod.executeVarargs(args);
-            Assert.assertEquals(expect, actual);
+            assertEquals(expect, actual);
         }
     }
 
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphScheduleTest.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphScheduleTest.java	Thu Jun 14 18:03:43 2012 +0200
@@ -40,7 +40,7 @@
         Block aBlock = nodeToBlock.get(a);
 
         if (bBlock == aBlock) {
-            List<Node> instructions = ibp.nodesFor(bBlock);
+            List<ScheduledNode> instructions = ibp.nodesFor(bBlock);
             Assert.assertTrue(instructions.indexOf(b) > instructions.indexOf(a));
         } else {
             Block block = bBlock;
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewInstanceTest.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewInstanceTest.java	Thu Jun 14 18:03:43 2012 +0200
@@ -26,25 +26,35 @@
 
 import org.junit.*;
 
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-
 /**
  * Tests the implementation of {@code NEW}.
  */
-public class NewInstanceTest extends TypeCheckTest {
+public class NewInstanceTest extends GraalCompilerTest {
 
     @Override
-    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
+    protected void assertEquals(Object expected, Object actual) {
+        Assert.assertTrue(expected != null);
+        Assert.assertTrue(actual != null);
+        super.assertEquals(expected.getClass(), actual.getClass());
     }
 
     @Test
     public void test1() {
+        test("newObject");
+        test("newBigObject");
         test("newEmptyString");
         test("newString", "value");
         test("newHashMap", 31);
     }
 
+    public static Object newObject() {
+        return new Object();
+    }
+
+    public static BigObject newBigObject() {
+        return new BigObject();
+    }
+
     public static String newEmptyString() {
         return new String();
     }
@@ -56,4 +66,51 @@
     public static HashMap newHashMap(int initialCapacity) {
         return new HashMap(initialCapacity);
     }
+
+    static class BigObject {
+        Object f01;
+        Object f02;
+        Object f03;
+        Object f04;
+        Object f05;
+        Object f06;
+        Object f07;
+        Object f08;
+        Object f09;
+        Object f10;
+        Object f12;
+        Object f13;
+        Object f14;
+        Object f15;
+        Object f16;
+        Object f17;
+        Object f18;
+        Object f19;
+        Object f20;
+        Object f21;
+        Object f22;
+        Object f23;
+        Object f24;
+        Object f25;
+        Object f26;
+        Object f27;
+        Object f28;
+        Object f29;
+        Object f30;
+        Object f31;
+        Object f32;
+        Object f33;
+        Object f34;
+        Object f35;
+        Object f36;
+        Object f37;
+        Object f38;
+        Object f39;
+        Object f40;
+        Object f41;
+        Object f42;
+        Object f43;
+        Object f44;
+        Object f45;
+    }
 }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/ScalarTypeSystemTest.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/ScalarTypeSystemTest.java	Thu Jun 14 18:03:43 2012 +0200
@@ -160,17 +160,14 @@
     }
 
     private void test(final String snippet, final String referenceSnippet) {
-        Debug.scope("ScalarTypeSystemTest", new DebugDumpScope(snippet), new Runnable() {
-            public void run() {
-                StructuredGraph graph = parse(snippet);
-                Debug.dump(graph, "Graph");
-//                TypeSystemTest.outputGraph(graph);
-                new CanonicalizerPhase(null, runtime(), null).apply(graph);
-                new CheckCastEliminationPhase().apply(graph);
-                new CanonicalizerPhase(null, runtime(), null).apply(graph);
-                StructuredGraph referenceGraph = parse(referenceSnippet);
-                assertEquals(referenceGraph, graph);
-            }
-        });
+        // No debug scope to reduce console noise for @Test(expected = ...) tests
+        StructuredGraph graph = parse(snippet);
+        Debug.dump(graph, "Graph");
+//        TypeSystemTest.outputGraph(graph);
+        new CanonicalizerPhase(null, runtime(), null).apply(graph);
+        new CheckCastEliminationPhase().apply(graph);
+        new CanonicalizerPhase(null, runtime(), null).apply(graph);
+        StructuredGraph referenceGraph = parse(referenceSnippet);
+        assertEquals(referenceGraph, graph);
     }
 }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/StraighteningTest.java	Thu Jun 14 18:03:18 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/StraighteningTest.java	Thu Jun 14 18:03:43 2012 +0200
@@ -85,14 +85,11 @@
     }
 
     private void test(final String snippet) {
-        Debug.scope("StraighteningTest", new DebugDumpScope(snippet), new Runnable() {
-            public void run() {
-                StructuredGraph graph = parse(snippet);
-                Debug.dump(graph, "Graph");
-                new CanonicalizerPhase(null, runtime(), null).apply(graph);
-                StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
-                assertEquals(referenceGraph, graph);
-            }
-        });
+        // No debug scope to reduce console noise for @Test(expected = ...) tests
+        StructuredGraph graph = parse(snippet);
+        Debug.dump(graph, "Graph");
+        new CanonicalizerPhase(null, runtime(), null).apply(graph);
+        StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
+        assertEquals(referenceGraph, graph);
     }
 }
--- a/mx/commands.py	Thu Jun 14 18:03:18 2012 +0200
+++ b/mx/commands.py	Thu Jun 14 18:03:43 2012 +0200
@@ -338,6 +338,11 @@
                 for line in lines:
                     f.write(line)
                     
+            # Install a copy of the disassembler library
+            try:
+                hsdis([], copyToDir=_vmLibDirInJdk(jdk))
+            except SystemExit:
+                pass
     else:
         if not exists(jdk):
             mx.abort('The ' + build + ' VM has not been created - run \'mx clean; mx build ' + build + '\'')
@@ -553,11 +558,12 @@
         vm = _vm
         
     build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product'
+    jdk = _jdk(build)
     mx.expand_project_in_args(args)
     if _make_eclipse_launch:
         mx.make_eclipse_launch(args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True))
     if len([a for a in args if 'PrintAssembly' in a]) != 0:
-        hsdis([])
+        hsdis([], copyToDir=_vmLibDirInJdk(jdk))
     if mx.java().debug_port is not None:
         args = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(mx.java().debug_port)] + args
     if _jacoco == 'on' or _jacoco == 'append':
@@ -573,7 +579,7 @@
                         'excludes' : ':'.join(excludes)
         }
         args = ['-javaagent:' + jacocoagent.get_path(True) + '=' + ','.join([k + '=' + v for k, v in agentOptions.items()])] + args
-    exe = join(_jdk(build), 'bin', mx.exe_suffix('java'))
+    exe = join(jdk, 'bin', mx.exe_suffix('java'))
     return mx.run([exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
 
 def _find_classes_with_annotations(classes, p, pkgRoot, annotations, includeInnerClasses=False):
@@ -967,19 +973,20 @@
     vm = _vm;
     sanitycheck.getSPECjvm2008(benchArgs, skipValid, wt, it).bench(vm, opts=vmArgs)
     
-def hsdis(args):
-    """install the hsdis library
+def hsdis(args, copyToDir=None):
+    """downloads the hsdis library
 
     This is needed to support HotSpot's assembly dumping features.
-    By default it installs the Intel syntax version, use the 'att' argument to install AT&T syntax."""
+    By default it downloads the Intel syntax version, use the 'att' argument to install AT&T syntax."""
     flavor = 'intel'
     if 'att' in args:
         flavor = 'att'
-    build = _vmbuild if _vmSourcesAvailable else 'product'
     lib = mx.lib_suffix('hsdis-amd64')
-    path = join(_vmLibDirInJdk(_jdk(build)), lib)
+    path = join(_graal_home, 'lib', lib)
     if not exists(path):
         mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavor + "/" + lib])
+    if copyToDir is not None and exists(copyToDir):
+        shutil.copy(path, copyToDir)
     
 def hcfdis(args):
     """disassembles HexCodeFiles embedded in text files
--- a/mxtool/mx.py	Thu Jun 14 18:03:18 2012 +0200
+++ b/mxtool/mx.py	Thu Jun 14 18:03:43 2012 +0200
@@ -172,6 +172,13 @@
         self.javaCompliance = JavaCompliance(javaCompliance) if javaCompliance is not None else None
         self.native = False
         self.dir = dir
+        
+        # Create directories for projects that don't yet exist
+        if not exists(dir):
+            os.mkdir(dir)
+        for s in self.source_dirs():
+            if not exists(s):
+                os.mkdir(s)
 
     def all_deps(self, deps, includeLibs, includeSelf=True):
         """
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Thu Jun 14 18:03:18 2012 +0200
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Thu Jun 14 18:03:43 2012 +0200
@@ -990,37 +990,6 @@
   return oop_maps;
 }
 
-#ifdef GRAAL
-JRT_ENTRY(void, graal_create_null_exception(JavaThread* thread))
-  thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_NullPointerException(), NULL)());
-JRT_END
-
-JRT_ENTRY(void, graal_create_out_of_bounds_exception(JavaThread* thread, jint index))
-  char message[jintAsStringSize];
-  sprintf(message, "%d", index);
-  thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message)());
-JRT_END
-
-JRT_ENTRY(void, graal_generic_callback(JavaThread* thread, oop _callback, oop _argument))
-  HandleMark hm;
-  Handle callback(_callback);
-  Handle argument(_argument);
-
-  KlassHandle klass = SystemDictionary::resolve_or_null(vmSymbols::com_oracle_graal_api_code_GenericCallback(), SystemDictionary::java_system_loader(), NULL, thread);
-  if (klass.is_null()) {
-    tty->print_cr("couldn't resolve com_oracle_graal_api_code_GenericCallback");
-  }
-
-  JavaValue result(T_OBJECT);
-  JavaCallArguments args;
-  args.push_oop(Handle(callback));
-  args.push_oop(Handle(argument));
-  JavaCalls::call_virtual(&result, klass, vmSymbols::callbackInternal_name(), vmSymbols::callback_signature(), &args, thread);
-
-  thread->set_vm_result((oop) result.get_jobject());
-JRT_END
-#endif
-
 OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
 
   // for better readability
@@ -1916,6 +1885,30 @@
       break;
     }
 
+    case graal_log_primitive_id: {
+      __ enter();
+      oop_maps = new OopMapSet();
+      OopMap* oop_map = save_live_registers(sasm, 0);
+      int call_offset = __ call_RT(noreg, noreg, (address)graal_log_primitive, j_rarg0, j_rarg1, j_rarg2);
+      oop_maps->add_gc_map(call_offset, oop_map);
+      restore_live_registers(sasm);
+      __ leave();
+      __ ret(0);
+      break;
+    }
+
+    case graal_log_object_id: {
+      __ enter();
+      oop_maps = new OopMapSet();
+      OopMap* oop_map = save_live_registers(sasm, 0);
+      int call_offset = __ call_RT(noreg, noreg, (address)graal_log_object, j_rarg0, j_rarg1, j_rarg2);
+      oop_maps->add_gc_map(call_offset, oop_map);
+      restore_live_registers(sasm);
+      __ leave();
+      __ ret(0);
+      break;
+    }
+
     case graal_generic_callback_id: {
     __ enter();
     oop_maps = new OopMapSet();
--- a/src/share/vm/c1/c1_Runtime1.cpp	Thu Jun 14 18:03:18 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Thu Jun 14 18:03:43 2012 +0200
@@ -648,6 +648,36 @@
 JRT_END
 
 #ifdef GRAAL
+
+JRT_ENTRY(void, Runtime1::graal_create_null_exception(JavaThread* thread))
+  thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_NullPointerException(), NULL)());
+JRT_END
+
+JRT_ENTRY(void, Runtime1::graal_create_out_of_bounds_exception(JavaThread* thread, jint index))
+  char message[jintAsStringSize];
+  sprintf(message, "%d", index);
+  thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message)());
+JRT_END
+
+JRT_ENTRY(void, Runtime1::graal_generic_callback(JavaThread* thread, oop _callback, oop _argument))
+  HandleMark hm;
+  Handle callback(_callback);
+  Handle argument(_argument);
+
+  KlassHandle klass = SystemDictionary::resolve_or_null(vmSymbols::com_oracle_graal_api_code_GenericCallback(), SystemDictionary::java_system_loader(), NULL, thread);
+  if (klass.is_null()) {
+    tty->print_cr("couldn't resolve com_oracle_graal_api_code_GenericCallback");
+  }
+
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(Handle(callback));
+  args.push_oop(Handle(argument));
+  JavaCalls::call_virtual(&result, klass, vmSymbols::callbackInternal_name(), vmSymbols::callback_signature(), &args, thread);
+
+  thread->set_vm_result((oop) result.get_jobject());
+JRT_END
+
 JRT_ENTRY_NO_ASYNC(void, Runtime1::graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock))
   NOT_PRODUCT(_monitorenter_slowcase_cnt++;)
 #ifdef ASSERT
@@ -708,7 +738,72 @@
   }
 JRT_END
 
-#endif
+JRT_ENTRY(void, Runtime1::graal_log_object(JavaThread* thread, oop obj, jboolean newline, jboolean string))
+  if (!string) {
+    tty->print("%p", obj);
+  } else {
+    assert(obj != NULL && java_lang_String::is_instance(obj), "must be");
+
+    typeArrayOop value  = java_lang_String::value(obj);
+    int          offset = java_lang_String::offset(obj);
+    int          length = java_lang_String::length(obj);
+
+    if (length != 0) {
+      int printLength = MIN2(length, 1024);
+      if (value == NULL) {
+        // This can happen if, e.g., printing a String
+        // object before its initializer has been called
+        tty->print("null");
+      } else if (printLength < 256 - 1) {
+        // Use an intermediate buffer to try and prevent interlacing of multi-threaded output
+        char buf[256];
+        for (int index = 0; index < printLength; index++) {
+          buf[index] = value->char_at(index + offset);
+        }
+        buf[printLength] = 0;
+        tty->print("%s", buf);
+        if (printLength < length) {
+          tty->print("... (%d more)", length - printLength);
+        }
+      } else {
+        for (int index = 0; index < printLength; index++) {
+          tty->print("%c", value->char_at(index + offset));
+        }
+        if (printLength < length) {
+          tty->print("... (%d more)", length - printLength);
+        }
+      }
+    }
+  }
+  if (newline) {
+    tty->cr();
+  }
+JRT_END
+
+JRT_ENTRY(void, Runtime1::graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline))
+  union {
+      jlong l;
+      jdouble d;
+      jfloat f;
+  } uu;
+  uu.l = value;
+  switch (typeChar) {
+    case 'z': tty->print(value == 0 ? "false" : "true"); break;
+    case 'b': tty->print("%d", (jbyte) value); break;
+    case 'c': tty->print("%c", (jchar) value); break;
+    case 's': tty->print("%d", (jshort) value); break;
+    case 'i': tty->print("%d", (jint) value); break;
+    case 'f': tty->print("%f", uu.f); break;
+    case 'j': tty->print(INT64_FORMAT, value); break;
+    case 'd': tty->print("%lf", uu.d); break;
+    default: assert(false, "unknown typeChar"); break;
+  }
+  if (newline) {
+    tty->cr();
+  }
+JRT_END
+
+#endif /* GRAAL */
 
 
 JRT_ENTRY_NO_ASYNC(void, Runtime1::monitorenter(JavaThread* thread, oopDesc* obj, BasicObjectLock* lock))
--- a/src/share/vm/c1/c1_Runtime1.hpp	Thu Jun 14 18:03:18 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.hpp	Thu Jun 14 18:03:43 2012 +0200
@@ -81,6 +81,8 @@
   stub(graal_create_null_pointer_exception) \
   stub(graal_create_out_of_bounds_exception) \
   stub(graal_generic_callback)       \
+  stub(graal_log_object)             \
+  stub(graal_log_primitive)          \
   last_entry(number_of_ids)
 #else
 #define RUNTIME1_STUBS(stub, last_entry) \
@@ -199,8 +201,13 @@
   static void monitorenter(JavaThread* thread, oopDesc* obj, BasicObjectLock* lock);
   static void monitorexit (JavaThread* thread, BasicObjectLock* lock);
 #ifdef GRAAL
+  static void graal_create_null_exception(JavaThread* thread);
+  static void graal_create_out_of_bounds_exception(JavaThread* thread, jint index);
+  static void graal_generic_callback(JavaThread* thread, oop _callback, oop _argument);
   static void graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock);
   static void graal_monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock);
+  static void graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);
+  static void graal_log_object(JavaThread* thread, oop msg, jboolean newline, jboolean string);
 #endif
 
   static void deoptimize(JavaThread* thread);
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Thu Jun 14 18:03:18 2012 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Thu Jun 14 18:03:43 2012 +0200
@@ -581,6 +581,12 @@
   } else if (runtime_call == RuntimeCall::GenericCallback()) {
     target_addr = Runtime1::entry_for(Runtime1::graal_generic_callback_id);
     TRACE_graal_3("RuntimeCall::GenericCallback()");
+  } else if (runtime_call == RuntimeCall::LogPrimitive()) {
+    target_addr = Runtime1::entry_for(Runtime1::graal_log_primitive_id);
+    TRACE_graal_3("RuntimeCall::LogPrimitive()");
+  } else if (runtime_call == RuntimeCall::LogObject()) {
+    target_addr = Runtime1::entry_for(Runtime1::graal_log_object_id);
+    TRACE_graal_3("RuntimeCall::LogObject()");
   } else {
     runtime_call->print();
     fatal("runtime_call not implemented");
@@ -598,7 +604,7 @@
 
   if (target_klass->is_subclass_of(SystemDictionary::Long_klass())) {
     global_stub = target;
-  } else if (target_klass->name() == vmSymbols::com_oracle_graal_api_code_RuntimeCall()) {
+  } else if (target->is_a(RuntimeCall::klass())) {
     runtime_call = target;
   } else {
     hotspot_method = target;
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Jun 14 18:03:18 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Jun 14 18:03:43 2012 +0200
@@ -785,6 +785,7 @@
   set_boolean(env, config, "useFastLocking", UseFastLocking);
   set_boolean(env, config, "useFastNewObjectArray", UseFastNewObjectArray);
   set_boolean(env, config, "useFastNewTypeArray", UseFastNewTypeArray);
+  set_boolean(env, config, "useTLAB", UseTLAB);
   set_int(env, config, "codeEntryAlignment", CodeEntryAlignment);
   set_int(env, config, "vmPageSize", os::vm_page_size());
   set_int(env, config, "stackShadowPages", StackShadowPages);
--- a/src/share/vm/graal/graalJavaAccess.hpp	Thu Jun 14 18:03:18 2012 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu Jun 14 18:03:43 2012 +0200
@@ -203,6 +203,8 @@
     static_oop_field(RuntimeCall, ArithmeticSin, "Lcom/oracle/graal/api/code/RuntimeCall;");   \
     static_oop_field(RuntimeCall, Deoptimize, "Lcom/oracle/graal/api/code/RuntimeCall;");      \
     static_oop_field(RuntimeCall, GenericCallback, "Lcom/oracle/graal/api/code/RuntimeCall;"); \
+    static_oop_field(RuntimeCall, LogPrimitive, "Lcom/oracle/graal/api/code/RuntimeCall;");    \
+    static_oop_field(RuntimeCall, LogObject, "Lcom/oracle/graal/api/code/RuntimeCall;");       \
   end_class                                                                             \
   start_class(JavaMethod)                                                                 \
   end_class                                                                             \