changeset 17146:2e4bd9de8682

Merge
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Wed, 17 Sep 2014 17:06:37 -0700
parents d75276c49399 (current diff) 62d7d16b170b (diff)
children 7a3f6543d383 5ecd1f298c64
files
diffstat 44 files changed, 493 insertions(+), 268 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -44,6 +44,11 @@
         this.name = name;
     }
 
+    public final void setAddress(long address) {
+        this.address = address;
+        version++;
+    }
+
     /**
      * @return the address of this code blob
      */
@@ -67,6 +72,13 @@
     }
 
     /**
+     * Returns the number of instruction bytes for this code.
+     */
+    public long getCodeSize() {
+        return 0;
+    }
+
+    /**
      * Returns a copy of this installed code if it is {@linkplain #isValid() valid}, null otherwise.
      */
     public byte[] getCode() {
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Wed Sep 17 17:06:37 2014 -0700
@@ -214,6 +214,15 @@
         assertEquals(1000L, annotation.timeout());
     }
 
+    @Test(timeout = 1000L)
+    public void getAnnotationsTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method = metaAccess.lookupJavaMethod(getClass().getDeclaredMethod("getAnnotationsTest"));
+        Annotation[] annotations = method.getAnnotations();
+        assertNotNull(annotations);
+        assertEquals(1, annotations.length);
+        assertEquals(1000L, ((Test) annotations[0]).timeout());
+    }
+
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.PARAMETER)
     @interface NonNull {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PrimitiveConstant.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PrimitiveConstant.java	Wed Sep 17 17:06:37 2014 -0700
@@ -123,7 +123,7 @@
         if (getKind() == Kind.Illegal) {
             return "illegal";
         } else {
-            return getKind().getJavaName() + "[" + getKind().format(asBoxedPrimitive()) + "|0x" + Long.toHexString(primitive) + "]";
+            return getKind().getJavaName() + "[" + asBoxedPrimitive() + "|0x" + Long.toHexString(primitive) + "]";
         }
     }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Wed Sep 17 17:06:37 2014 -0700
@@ -141,6 +141,12 @@
     ConstantPool getConstantPool();
 
     /**
+     * Returns all annotations of this method. If no annotations are present, an array of length 0
+     * is returned.
+     */
+    Annotation[] getAnnotations();
+
+    /**
      * Returns the annotation for the specified type of this method, if such an annotation is
      * present.
      *
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Wed Sep 17 17:06:37 2014 -0700
@@ -95,7 +95,7 @@
             BciBlockMapping blockMap;
             try (Scope ds = Debug.scope("BciBlockMapping")) {
                 // compute the block map, setup exception handlers and get the entrypoint(s)
-                blockMap = BciBlockMapping.create(method);
+                blockMap = BciBlockMapping.create(method, graphBuilderConfig.doLivenessAnalysis());
             } catch (Throwable e) {
                 throw Debug.handle(e);
             }
@@ -158,7 +158,7 @@
                 try (Scope s = Debug.scope("Allocator")) {
 
                     if (backend.shouldAllocateRegisters()) {
-                        new LinearScan(target, lir, frameMap).allocate();
+                        LinearScan.allocate(target, lir, frameMap);
                     }
                 } catch (Throwable e) {
                     throw Debug.handle(e);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Sep 17 17:06:37 2014 -0700
@@ -269,7 +269,7 @@
 
             try (Scope s = Debug.scope("Allocator", nodeLirGen)) {
                 if (backend.shouldAllocateRegisters()) {
-                    new LinearScan(target, lir, frameMap).allocate();
+                    LinearScan.allocate(target, lir, frameMap);
                 }
             } catch (Throwable e) {
                 throw Debug.handle(e);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed Sep 17 17:06:37 2014 -0700
@@ -1856,7 +1856,11 @@
         }
     }
 
-    public void allocate() {
+    public static void allocate(TargetDescription target, LIR lir, FrameMap frameMap) {
+        new LinearScan(target, lir, frameMap).allocate();
+    }
+
+    private void allocate() {
 
         /*
          * This is the point to enable debug logging for the whole register allocation.
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Sep 17 17:06:37 2014 -0700
@@ -30,12 +30,18 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.options.*;
 
 /**
  * This class is a graph container, it contains the set of nodes that belong to this graph.
  */
 public class Graph {
 
+    static class Options {
+        @Option(help = "Verify graphs often during compilation when assertions are turned on")//
+        public static final OptionValue<Boolean> VerifyGraalGraphs = new OptionValue<>(true);
+    }
+
     public final String name;
 
     /**
@@ -566,7 +572,7 @@
      * mark}.
      */
     public NodeIterable<Node> getNewNodes(Mark mark) {
-        final int index = mark.getValue();
+        final int index = mark == null ? 0 : mark.getValue();
         return new NodeIterable<Node>() {
 
             @Override
@@ -752,17 +758,19 @@
     }
 
     public boolean verify() {
-        for (Node node : getNodes()) {
-            try {
+        if (Options.VerifyGraalGraphs.getValue()) {
+            for (Node node : getNodes()) {
                 try {
-                    assert node.verify();
-                } catch (AssertionError t) {
-                    throw new GraalInternalError(t);
-                } catch (RuntimeException t) {
-                    throw new GraalInternalError(t);
+                    try {
+                        assert node.verify();
+                    } catch (AssertionError t) {
+                        throw new GraalInternalError(t);
+                    } catch (RuntimeException t) {
+                        throw new GraalInternalError(t);
+                    }
+                } catch (GraalInternalError e) {
+                    throw GraalGraphInternalError.transformAndAddContext(e, node).addContext(this);
                 }
-            } catch (GraalInternalError e) {
-                throw GraalGraphInternalError.transformAndAddContext(e, node).addContext(this);
             }
         }
         return true;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Sep 17 17:06:37 2014 -0700
@@ -254,7 +254,7 @@
                 }
                 if (nodeClass.getClazz().isAssignableFrom(clazz) && IterableNodeType.class.isAssignableFrom(nodeClass.getClazz())) {
                     NodeClass superNodeClass = (NodeClass) nodeClass;
-                    if (!USE_GENERATED_NODES || !containsId(this.iterableId, superNodeClass.iterableIds)) {
+                    if (!containsId(this.iterableId, superNodeClass.iterableIds)) {
                         superNodeClass.iterableIds = Arrays.copyOf(superNodeClass.iterableIds, superNodeClass.iterableIds.length + 1);
                         superNodeClass.iterableIds[superNodeClass.iterableIds.length - 1] = this.iterableId;
                     }
@@ -346,7 +346,7 @@
      *
      * <pre>
      *     if (node.getNodeClass().is(BeginNode.class)) { ... }
-     *
+     * 
      *     // Due to generated Node classes, the test below
      *     // is *not* the same as the test above:
      *     if (node.getClass() == BeginNode.class) { ... }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Wed Sep 17 17:06:37 2014 -0700
@@ -166,7 +166,7 @@
         } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) {
             // Nothing to do for division nodes. The HotSpot signal handler catches divisions by
             // zero and the MIN_VALUE / -1 cases.
-        } else if (n instanceof DeoptimizeNode || n instanceof UnwindNode || n instanceof FloatRemNode) {
+        } else if (n instanceof AbstractDeoptimizeNode || n instanceof UnwindNode || n instanceof FloatRemNode) {
             /* No lowering, we generate LIR directly for these nodes. */
         } else {
             super.lower(n, tool);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -80,6 +80,7 @@
         return codeStart;
     }
 
+    @Override
     public long getCodeSize() {
         return codeSize;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed Sep 17 17:06:37 2014 -0700
@@ -461,6 +461,16 @@
     }
 
     @Override
+    public Annotation[] getAnnotations() {
+        if (isConstructor()) {
+            Constructor<?> javaConstructor = toJavaConstructor();
+            return javaConstructor == null ? new Annotation[0] : javaConstructor.getAnnotations();
+        }
+        Method javaMethod = toJava();
+        return javaMethod == null ? new Annotation[0] : javaMethod.getAnnotations();
+    }
+
+    @Override
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
         if (isConstructor()) {
             Constructor<?> javaConstructor = toJavaConstructor();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -185,6 +185,10 @@
         return uninitialized;
     }
 
+    static boolean isHeapWordAligned(Constant value, Kind kind) {
+        return (arrayBaseOffset(kind) + (long) value.asInt() * arrayIndexScale(kind)) % heapWordSize() == 0;
+    }
+
     public void updateAlignedDisjoint() {
         Kind componentKind = elementKind;
         if (srcPos == destPos) {
@@ -195,7 +199,7 @@
         Constant constantDst = destPos.stamp().asConstant();
         if (constantSrc != null && constantDst != null) {
             if (!aligned) {
-                aligned = ArrayCopyNode.isHeapWordAligned(constantSrc, componentKind) && ArrayCopyNode.isHeapWordAligned(constantDst, componentKind);
+                aligned = isHeapWordAligned(constantSrc, componentKind) && isHeapWordAligned(constantDst, componentKind);
             }
             if (constantSrc.asInt() >= constantDst.asInt()) {
                 // low to high copy so treat as disjoint
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.compiler.GraalCompiler.*;
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
@@ -34,13 +33,12 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.nodes.*;
 
 @NodeInfo
-public class ArrayCopyNode extends MacroStateSplitNode implements Virtualizable, Lowerable {
+public class ArrayCopyNode extends BasicArrayCopyNode implements Virtualizable, Lowerable {
 
     public static ArrayCopyNode create(Invoke invoke) {
         return USE_GENERATED_NODES ? new ArrayCopyNodeGen(invoke) : new ArrayCopyNode(invoke);
@@ -50,30 +48,6 @@
         super(invoke);
     }
 
-    private ValueNode getSource() {
-        return arguments.get(0);
-    }
-
-    private ValueNode getSourcePosition() {
-        return arguments.get(1);
-    }
-
-    private ValueNode getDestination() {
-        return arguments.get(2);
-    }
-
-    private ValueNode getDestinationPosition() {
-        return arguments.get(3);
-    }
-
-    private ValueNode getLength() {
-        return arguments.get(4);
-    }
-
-    static boolean isHeapWordAligned(Constant value, Kind kind) {
-        return (arrayBaseOffset(kind) + (long) value.asInt() * arrayIndexScale(kind)) % heapWordSize() == 0;
-    }
-
     private StructuredGraph selectSnippet(LoweringTool tool, final Replacements replacements) {
         ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp());
         ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp());
@@ -162,67 +136,4 @@
         }
         return false;
     }
-
-    private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) {
-        return position >= 0 && position + length <= virtualObject.entryCount();
-    }
-
-    private static boolean checkEntryTypes(int srcPos, int length, State srcState, ResolvedJavaType destComponentType, VirtualizerTool tool) {
-        if (destComponentType.getKind() == Kind.Object) {
-            for (int i = 0; i < length; i++) {
-                ValueNode entry = srcState.getEntry(srcPos + i);
-                State state = tool.getObjectState(entry);
-                ResolvedJavaType type;
-                if (state != null) {
-                    if (state.getState() == EscapeState.Virtual) {
-                        type = state.getVirtualObject().type();
-                    } else {
-                        type = StampTool.typeOrNull(state.getMaterializedValue());
-                    }
-                } else {
-                    type = StampTool.typeOrNull(entry);
-                }
-                if (type == null || !destComponentType.isAssignableFrom(type)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public void virtualize(VirtualizerTool tool) {
-        if (getSourcePosition().isConstant() && getDestinationPosition().isConstant() && getLength().isConstant()) {
-            int srcPos = getSourcePosition().asConstant().asInt();
-            int destPos = getDestinationPosition().asConstant().asInt();
-            int length = getLength().asConstant().asInt();
-            State srcState = tool.getObjectState(getSource());
-            State destState = tool.getObjectState(getDestination());
-
-            if (srcState != null && srcState.getState() == EscapeState.Virtual && destState != null && destState.getState() == EscapeState.Virtual) {
-                VirtualObjectNode srcVirtual = srcState.getVirtualObject();
-                VirtualObjectNode destVirtual = destState.getVirtualObject();
-                if (!(srcVirtual instanceof VirtualArrayNode) || !(destVirtual instanceof VirtualArrayNode)) {
-                    return;
-                }
-                if (((VirtualArrayNode) srcVirtual).componentType().getKind() != Kind.Object || ((VirtualArrayNode) destVirtual).componentType().getKind() != Kind.Object) {
-                    return;
-                }
-                if (length < 0 || !checkBounds(srcPos, length, srcVirtual) || !checkBounds(destPos, length, destVirtual)) {
-                    return;
-                }
-                if (!checkEntryTypes(srcPos, length, srcState, destVirtual.type().getComponentType(), tool)) {
-                    return;
-                }
-                for (int i = 0; i < length; i++) {
-                    tool.setVirtualEntry(destState, destPos + i, srcState.getEntry(srcPos + i), false);
-                }
-                tool.delete();
-                if (Debug.isLogEnabled()) {
-                    Debug.log("virtualized arraycopyf(%s, %d, %s, %d, %d)", getSource(), srcPos, getDestination(), destPos, length);
-                }
-            }
-        }
-    }
-
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -25,11 +25,8 @@
 import static com.oracle.graal.compiler.GraalCompiler.*;
 
 import java.lang.reflect.*;
-import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodeinfo.*;
@@ -37,11 +34,10 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.replacements.nodes.*;
 
 @NodeInfo
-public class ObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider {
+public class ObjectCloneNode extends BasicObjectCloneNode implements VirtualizableAllocation, ArrayLengthProvider {
 
     public static ObjectCloneNode create(Invoke invoke) {
         return USE_GENERATED_NODES ? new ObjectCloneNodeGen(invoke) : new ObjectCloneNode(invoke);
@@ -52,15 +48,6 @@
     }
 
     @Override
-    public boolean inferStamp() {
-        return updateStamp(getObject().stamp());
-    }
-
-    private ValueNode getObject() {
-        return arguments.get(0);
-    }
-
-    @Override
     protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) {
         if (!shouldIntrinsify(getTargetMethod())) {
             return null;
@@ -105,81 +92,4 @@
         }
         return null;
     }
-
-    private static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) {
-        return metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type);
-    }
-
-    /*
-     * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an
-     * exact type) and if it is a cloneable type.
-     * 
-     * If yes, then the exact type is returned, otherwise it returns null.
-     */
-    private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) {
-        if (!(stamp instanceof ObjectStamp)) {
-            return null;
-        }
-        ObjectStamp objectStamp = (ObjectStamp) stamp;
-        if (objectStamp.type() == null) {
-            return null;
-        } else if (objectStamp.isExactType()) {
-            return isCloneableType(objectStamp.type(), metaAccess) ? objectStamp.type() : null;
-        } else {
-            ResolvedJavaType type = objectStamp.type().findUniqueConcreteSubtype();
-            if (type != null && isCloneableType(type, metaAccess)) {
-                assumptions.recordConcreteSubtype(objectStamp.type(), type);
-                return type;
-            } else {
-                return null;
-            }
-        }
-    }
-
-    @Override
-    public void virtualize(VirtualizerTool tool) {
-        State originalState = tool.getObjectState(getObject());
-        if (originalState != null && originalState.getState() == EscapeState.Virtual) {
-            VirtualObjectNode originalVirtual = originalState.getVirtualObject();
-            if (isCloneableType(originalVirtual.type(), tool.getMetaAccessProvider())) {
-                ValueNode[] newEntryState = new ValueNode[originalVirtual.entryCount()];
-                for (int i = 0; i < newEntryState.length; i++) {
-                    newEntryState[i] = originalState.getEntry(i);
-                }
-                VirtualObjectNode newVirtual = originalVirtual.duplicate();
-                tool.createVirtualObject(newVirtual, newEntryState, Collections.<MonitorIdNode> emptyList());
-                tool.replaceWithVirtual(newVirtual);
-            }
-        } else {
-            ValueNode obj;
-            if (originalState != null) {
-                obj = originalState.getMaterializedValue();
-            } else {
-                obj = tool.getReplacedValue(getObject());
-            }
-            ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions(), tool.getMetaAccessProvider());
-            if (type != null && !type.isArray()) {
-                VirtualInstanceNode newVirtual = VirtualInstanceNode.create(type, true);
-                ResolvedJavaField[] fields = newVirtual.getFields();
-
-                ValueNode[] state = new ValueNode[fields.length];
-                final LoadFieldNode[] loads = new LoadFieldNode[fields.length];
-                for (int i = 0; i < fields.length; i++) {
-                    state[i] = loads[i] = LoadFieldNode.create(obj, fields[i]);
-                    tool.addNode(loads[i]);
-                }
-                tool.createVirtualObject(newVirtual, state, Collections.<MonitorIdNode> emptyList());
-                tool.replaceWithVirtual(newVirtual);
-            }
-        }
-    }
-
-    @Override
-    public ValueNode length() {
-        if (getObject() instanceof ArrayLengthProvider) {
-            return ((ArrayLengthProvider) getObject()).length();
-        } else {
-            return null;
-        }
-    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Wed Sep 17 17:06:37 2014 -0700
@@ -64,7 +64,7 @@
 
     protected F frameState;
     protected BytecodeStream stream;
-    private GraphBuilderConfiguration graphBuilderConfig;
+    protected GraphBuilderConfiguration graphBuilderConfig;
     protected ResolvedJavaMethod method;
     protected BciBlock currentBlock;
     protected ProfilingInfo profilingInfo;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Sep 17 17:06:37 2014 -0700
@@ -273,6 +273,7 @@
     private BciBlock[] blockMap;
     public BciBlock[] loopHeaders;
 
+    private final boolean doLivenessAnalysis;
     public LocalLiveness liveness;
 
     /**
@@ -280,7 +281,8 @@
      *
      * @param method the compiler interface method containing the code
      */
-    private BciBlockMapping(ResolvedJavaMethod method) {
+    private BciBlockMapping(ResolvedJavaMethod method, boolean doLivenessAnalysis) {
+        this.doLivenessAnalysis = doLivenessAnalysis;
         this.method = method;
         exceptionHandlers = method.getExceptionHandlers();
         stream = new BytecodeStream(method.getCode());
@@ -319,7 +321,7 @@
         if (Debug.isLogEnabled()) {
             this.log("Before LivenessAnalysis");
         }
-        if (OptLivenessAnalysis.getValue()) {
+        if (doLivenessAnalysis) {
             try (Scope s = Debug.scope("LivenessAnalysis")) {
                 liveness = method.getMaxLocals() <= 64 ? new SmallLocalLiveness() : new LargeLocalLiveness();
                 liveness.computeLiveness();
@@ -1058,8 +1060,8 @@
         }
     }
 
-    public static BciBlockMapping create(ResolvedJavaMethod method) {
-        BciBlockMapping map = new BciBlockMapping(method);
+    public static BciBlockMapping create(ResolvedJavaMethod method, boolean doLivenessAnalysis) {
+        BciBlockMapping map = new BciBlockMapping(method, doLivenessAnalysis);
         map.build();
         if (Debug.isDumpEnabled()) {
             Debug.dump(map, method.format("After block building %f %R %H.%n(%P)"));
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Wed Sep 17 17:06:37 2014 -0700
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.nodes.*;
 
 public class GraphBuilderConfiguration {
@@ -34,6 +35,7 @@
     private final boolean omitAllExceptionEdges;
     private final ResolvedJavaType[] skippedExceptionTypes;
     private final DebugInfoMode debugInfoMode;
+    private final boolean doLivenessAnalysis;
 
     public static enum DebugInfoMode {
         SafePointsOnly,
@@ -59,20 +61,25 @@
         Full,
     }
 
-    protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes) {
+    protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes, boolean doLivenessAnalysis) {
         this.eagerResolving = eagerResolving;
         this.omitAllExceptionEdges = omitAllExceptionEdges;
         this.debugInfoMode = debugInfoMode;
         this.skippedExceptionTypes = skippedExceptionTypes;
+        this.doLivenessAnalysis = doLivenessAnalysis;
     }
 
     public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) {
-        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, newSkippedExceptionTypes);
+        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis);
     }
 
     public GraphBuilderConfiguration withDebugInfoMode(DebugInfoMode newDebugInfoMode) {
         ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length);
-        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newDebugInfoMode, newSkippedExceptionTypes);
+        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newDebugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis);
+    }
+
+    public GraphBuilderConfiguration withDoLivenessAnalysis(boolean newLivenessAnalysis) {
+        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, newLivenessAnalysis);
     }
 
     public ResolvedJavaType[] getSkippedExceptionTypes() {
@@ -95,20 +102,24 @@
         return debugInfoMode.ordinal() >= DebugInfoMode.Full.ordinal();
     }
 
+    public boolean doLivenessAnalysis() {
+        return doLivenessAnalysis;
+    }
+
     public static GraphBuilderConfiguration getDefault() {
-        return new GraphBuilderConfiguration(false, false, DebugInfoMode.SafePointsOnly, EMPTY);
+        return new GraphBuilderConfiguration(false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue());
     }
 
     public static GraphBuilderConfiguration getEagerDefault() {
-        return new GraphBuilderConfiguration(true, false, DebugInfoMode.SafePointsOnly, EMPTY);
+        return new GraphBuilderConfiguration(true, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue());
     }
 
     public static GraphBuilderConfiguration getSnippetDefault() {
-        return new GraphBuilderConfiguration(true, true, DebugInfoMode.SafePointsOnly, EMPTY);
+        return new GraphBuilderConfiguration(true, true, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue());
     }
 
     public static GraphBuilderConfiguration getFullDebugDefault() {
-        return new GraphBuilderConfiguration(true, false, DebugInfoMode.Full, EMPTY);
+        return new GraphBuilderConfiguration(true, false, DebugInfoMode.Full, EMPTY, GraalOptions.OptLivenessAnalysis.getValue());
     }
 
     /**
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Sep 17 17:06:37 2014 -0700
@@ -230,7 +230,7 @@
                 try (Indent indent = Debug.logAndIndent("build graph for %s", method)) {
 
                     // compute the block map, setup exception handlers and get the entrypoint(s)
-                    BciBlockMapping blockMap = BciBlockMapping.create(method);
+                    BciBlockMapping blockMap = BciBlockMapping.create(method, graphBuilderConfig.doLivenessAnalysis());
                     loopHeaders = blockMap.loopHeaders;
                     liveness = blockMap.liveness;
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Wed Sep 17 17:06:37 2014 -0700
@@ -33,7 +33,7 @@
 
 public class LIRInstructionClass extends LIRIntrospection {
 
-    static final LIRInstructionClass get(Class<? extends LIRInstruction> c) {
+    public static final LIRInstructionClass get(Class<? extends LIRInstruction> c) {
         LIRInstructionClass clazz = (LIRInstructionClass) allClasses.get(c);
         if (clazz != null) {
             return clazz;
@@ -76,7 +76,7 @@
     }
 
     @SuppressWarnings("unchecked")
-    private LIRInstructionClass(Class<? extends LIRInstruction> clazz, CalcOffset calcOffset) {
+    public LIRInstructionClass(Class<? extends LIRInstruction> clazz, CalcOffset calcOffset) {
         super(clazz);
         assert INSTRUCTION_CLASS.isAssignableFrom(clazz);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable, Canonicalizable {
+public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable, Lowerable, Canonicalizable {
     @Input ValueNode actionAndReason;
     @Input ValueNode speculation;
 
@@ -60,6 +60,11 @@
         return getSpeculation();
     }
 
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+
     public void generate(NodeLIRBuilderTool generator) {
         generator.getLIRGeneratorTool().emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), generator.state(this));
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -30,8 +30,8 @@
 @NodeInfo
 public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode implements Canonicalizable.Binary<ValueNode> {
 
-    @Input ValueNode x;
-    @Input ValueNode y;
+    @Input protected ValueNode x;
+    @Input protected ValueNode y;
 
     public FixedBinaryNode(Stamp stamp, ValueNode x, ValueNode y) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -48,7 +48,7 @@
         return USE_GENERATED_NODES ? new ForeignCallNodeGen(foreignCalls, descriptor, arguments) : new ForeignCallNode(foreignCalls, descriptor, arguments);
     }
 
-    ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) {
+    protected ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) {
         super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())));
         this.arguments = new NodeInputList<>(this, arguments);
         this.descriptor = descriptor;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -43,7 +43,7 @@
 @NodeInfo
 public class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Simplifiable, Lowerable, Virtualizable, ValueProxy {
 
-    @Input ValueNode object;
+    @Input protected ValueNode object;
     private final ResolvedJavaType type;
     private final JavaTypeProfile profile;
 
@@ -63,7 +63,7 @@
         return USE_GENERATED_NODES ? new CheckCastNodeGen(type, object, profile, forStoreCheck) : new CheckCastNode(type, object, profile, forStoreCheck);
     }
 
-    CheckCastNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) {
+    protected CheckCastNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) {
         super(StampFactory.declared(type));
         assert type != null;
         this.type = type;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -49,7 +49,7 @@
         return USE_GENERATED_NODES ? new InstanceOfNodeGen(type, object, profile) : new InstanceOfNode(type, object, profile);
     }
 
-    InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) {
+    protected InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) {
         super(object);
         this.type = type;
         this.profile = profile;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -41,7 +41,7 @@
         return USE_GENERATED_NODES ? new MethodCallTargetNodeGen(invokeKind, targetMethod, arguments, returnType) : new MethodCallTargetNode(invokeKind, targetMethod, arguments, returnType);
     }
 
-    MethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType) {
+    protected MethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType) {
         super(arguments, targetMethod, invokeKind);
         this.returnType = returnType;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -81,13 +81,17 @@
                 for (int i = 0; i < constantLength; i++) {
                     state[i] = defaultForKind;
                 }
-                VirtualObjectNode virtualObject = VirtualArrayNode.create(elementType(), constantLength);
+                VirtualObjectNode virtualObject = createVirtualArrayNode(constantLength);
                 tool.createVirtualObject(virtualObject, state, Collections.<MonitorIdNode> emptyList());
                 tool.replaceWithVirtual(virtualObject);
             }
         }
     }
 
+    protected VirtualArrayNode createVirtualArrayNode(int constantLength) {
+        return VirtualArrayNode.create(elementType(), constantLength);
+    }
+
     /* Factored out in a separate method so that subclasses can override it. */
     protected ConstantNode defaultElementValue() {
         return ConstantNode.defaultForKind(elementType().getKind(), graph());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -51,7 +51,7 @@
         return USE_GENERATED_NODES ? new NewInstanceNodeGen(type, fillContents) : new NewInstanceNode(type, fillContents);
     }
 
-    NewInstanceNode(ResolvedJavaType type, boolean fillContents) {
+    protected NewInstanceNode(ResolvedJavaType type, boolean fillContents) {
         super(StampFactory.exactNonNull(type), fillContents);
         assert !type.isArray() && !type.isInterface() && !type.isPrimitive();
         this.instanceClass = type;
@@ -73,7 +73,7 @@
          * they're excluded from escape analysis.
          */
         if (!tool.getMetaAccessProvider().lookupJavaType(Reference.class).isAssignableFrom(instanceClass)) {
-            VirtualInstanceNode virtualObject = VirtualInstanceNode.create(instanceClass(), true);
+            VirtualInstanceNode virtualObject = createVirtualInstanceNode(true);
             ResolvedJavaField[] fields = virtualObject.getFields();
             ValueNode[] state = new ValueNode[fields.length];
             for (int i = 0; i < state.length; i++) {
@@ -84,6 +84,10 @@
         }
     }
 
+    protected VirtualInstanceNode createVirtualInstanceNode(boolean hasIdentity) {
+        return VirtualInstanceNode.create(instanceClass(), hasIdentity);
+    }
+
     /* Factored out in a separate method so that subclasses can override it. */
     protected ConstantNode defaultFieldValue(ResolvedJavaField field) {
         return ConstantNode.defaultForKind(field.getType().getKind(), graph());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -35,7 +35,7 @@
 @NodeInfo
 public class NewMultiArrayNode extends DeoptimizingFixedWithNextNode implements Lowerable, ArrayLengthProvider {
 
-    @Input NodeInputList<ValueNode> dimensions;
+    @Input protected NodeInputList<ValueNode> dimensions;
     private final ResolvedJavaType type;
 
     public ValueNode dimension(int index) {
@@ -60,7 +60,7 @@
         return USE_GENERATED_NODES ? new NewMultiArrayNodeGen(type, dimensions) : new NewMultiArrayNode(type, dimensions);
     }
 
-    NewMultiArrayNode(ResolvedJavaType type, ValueNode[] dimensions) {
+    protected NewMultiArrayNode(ResolvedJavaType type, ValueNode[] dimensions) {
         super(StampFactory.exactNonNull(type));
         this.type = type;
         this.dimensions = new NodeInputList<>(this, dimensions);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -32,14 +32,14 @@
 @NodeInfo(nameTemplate = "VirtualArray {p#componentType/s}[{p#length}]")
 public class VirtualArrayNode extends VirtualObjectNode implements ArrayLengthProvider {
 
-    private final ResolvedJavaType componentType;
-    private final int length;
+    protected final ResolvedJavaType componentType;
+    protected final int length;
 
     public static VirtualArrayNode create(ResolvedJavaType componentType, int length) {
         return USE_GENERATED_NODES ? new VirtualArrayNodeGen(componentType, length) : new VirtualArrayNode(componentType, length);
     }
 
-    VirtualArrayNode(ResolvedJavaType componentType, int length) {
+    protected VirtualArrayNode(ResolvedJavaType componentType, int length) {
         super(componentType.getArrayClass(), true);
         this.componentType = componentType;
         this.length = length;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -41,6 +41,10 @@
         this.boxingKind = boxingKind;
     }
 
+    public Kind getBoxingKind() {
+        return boxingKind;
+    }
+
     @Override
     public VirtualBoxingNode duplicate() {
         return VirtualBoxingNode.create(type(), boxingKind);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -29,14 +29,14 @@
 @NodeInfo(nameTemplate = "VirtualInstance {p#type/s}")
 public class VirtualInstanceNode extends VirtualObjectNode {
 
-    private final ResolvedJavaType type;
-    private final ResolvedJavaField[] fields;
+    protected final ResolvedJavaType type;
+    protected final ResolvedJavaField[] fields;
 
     public static VirtualInstanceNode create(ResolvedJavaType type, boolean hasIdentity) {
         return USE_GENERATED_NODES ? new VirtualInstanceNodeGen(type, hasIdentity) : new VirtualInstanceNode(type, hasIdentity);
     }
 
-    VirtualInstanceNode(ResolvedJavaType type, boolean hasIdentity) {
+    protected VirtualInstanceNode(ResolvedJavaType type, boolean hasIdentity) {
         this(type, type.getInstanceFields(true), hasIdentity);
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Sep 17 17:06:37 2014 -0700
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
@@ -57,11 +56,13 @@
                     if (target instanceof AbstractDeoptimizeNode) {
                         merge = graph.add(MergeNode.create());
                         EndNode firstEnd = graph.add(EndNode.create());
-                        reasonActionPhi = graph.addWithoutUnique(ValuePhiNode.create(StampFactory.forKind(Kind.Int), merge));
-                        speculationPhi = graph.addWithoutUnique(ValuePhiNode.create(StampFactory.forKind(Kind.Object), merge));
+                        ValueNode actionAndReason = ((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess());
+                        ValueNode speculation = ((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess());
+                        reasonActionPhi = graph.addWithoutUnique(ValuePhiNode.create(StampFactory.forKind(actionAndReason.getKind()), merge));
+                        speculationPhi = graph.addWithoutUnique(ValuePhiNode.create(StampFactory.forKind(speculation.getKind()), merge));
                         merge.addForwardEnd(firstEnd);
-                        reasonActionPhi.addInput(((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess()));
-                        speculationPhi.addInput(((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess()));
+                        reasonActionPhi.addInput(actionAndReason);
+                        speculationPhi.addInput(speculation);
                         target.replaceAtPredecessor(firstEnd);
 
                         exitLoops((AbstractDeoptimizeNode) target, firstEnd, cfg);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Wed Sep 17 17:06:37 2014 -0700
@@ -146,7 +146,9 @@
                 graph.addBeforeFixed(before, fixedGuard);
                 DummyGuardHandle handle = graph.add(DummyGuardHandle.create(fixedGuard));
                 fixedGuard.lower(this);
-                return handle.getGuard();
+                GuardingNode result = handle.getGuard();
+                handle.safeDelete();
+                return result;
             } else {
                 GuardNode newGuard = graph.unique(GuardNode.create(condition, guardAnchor, deoptReason, action, negated, Constant.NULL_OBJECT));
                 if (OptEliminateGuards.getValue()) {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Wed Sep 17 17:06:37 2014 -0700
@@ -50,7 +50,7 @@
      * Gets a global output stream on a file in the current working directory. This stream is first
      * opened if necessary. The name of the file is
      * {@code "compilations-" + System.currentTimeMillis() + ".cfg"}.
-     * 
+     *
      * @return the global output stream or {@code null} if there was an error opening the file for
      *         writing
      */
@@ -70,7 +70,7 @@
 
     /**
      * Creates a control flow graph printer.
-     * 
+     *
      * @param os where the output generated via this printer will be sent
      */
     public CompilationPrinter(OutputStream os) {
@@ -101,7 +101,7 @@
 
     /**
      * Prints a compilation timestamp for a given method.
-     * 
+     *
      * @param method the method for which a timestamp will be printed
      */
     public void printCompilation(JavaMethod method) {
@@ -227,7 +227,7 @@
     }
 
     public void printBytecodes(String code) {
-        if (code.length() == 0) {
+        if (code == null || code.length() == 0) {
             return;
         }
         begin("bytecodes");
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Wed Sep 17 17:06:37 2014 -0700
@@ -346,9 +346,9 @@
                 int entryCount = virtual.entryCount();
                 AbstractNewObjectNode newObject;
                 if (virtual instanceof VirtualInstanceNode) {
-                    newObject = graph.add(NewInstanceNode.create(virtual.type(), true));
+                    newObject = graph.add(createNewInstanceFromVirtual(virtual));
                 } else {
-                    newObject = graph.add(NewArrayNode.create(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true));
+                    newObject = graph.add(createNewArrayFromVirtual(virtual, ConstantNode.forInt(entryCount, graph)));
                 }
                 recursiveLowerings.add(newObject);
                 graph.addBeforeFixed(commit, newObject);
@@ -433,6 +433,14 @@
         }
     }
 
+    public NewInstanceNode createNewInstanceFromVirtual(VirtualObjectNode virtual) {
+        return NewInstanceNode.create(virtual.type(), true);
+    }
+
+    protected NewArrayNode createNewArrayFromVirtual(VirtualObjectNode virtual, ValueNode length) {
+        return NewArrayNode.create(((VirtualArrayNode) virtual).componentType(), length, true);
+    }
+
     public static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) {
         StructuredGraph graph = commit.graph();
         for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Wed Sep 17 17:06:37 2014 -0700
@@ -137,7 +137,7 @@
             if (invoke.getKind() != Kind.Void) {
                 frameStateBuilder.push(invoke.getKind(), invoke);
             }
-            invoke.setStateAfter(frameStateBuilder.create(0));
+            invoke.setStateAfter(frameStateBuilder.create(bci));
             if (invoke.getKind() != Kind.Void) {
                 frameStateBuilder.pop(invoke.getKind());
             }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Wed Sep 17 17:06:37 2014 -0700
@@ -208,7 +208,7 @@
         return result;
     }
 
-    private Node createNodeInstance(StructuredGraph graph, ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType,
+    protected Node createNodeInstance(StructuredGraph graph, ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType,
                     Constant[] nodeFactoryArguments) {
         ResolvedJavaMethod factory = null;
         Constant[] arguments = null;
@@ -233,7 +233,7 @@
         }
 
         try {
-            ValueNode intrinsicNode = (ValueNode) snippetReflection.asObject(factory.invoke(null, arguments));
+            ValueNode intrinsicNode = (ValueNode) snippetReflection.asObject(invokeFactory(factory, arguments));
 
             if (setStampFromReturnType) {
                 intrinsicNode.setStamp(invokeStamp);
@@ -244,6 +244,10 @@
         }
     }
 
+    protected Constant invokeFactory(ResolvedJavaMethod factory, Constant[] arguments) {
+        return factory.invoke(null, arguments);
+    }
+
     private static String sigString(ResolvedJavaType[] types) {
         StringBuilder sb = new StringBuilder("(");
         for (int i = 0; i < types.length; i++) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Wed Sep 17 17:06:37 2014 -0700
@@ -75,9 +75,9 @@
      * Encapsulates method and macro substitutions for a single class.
      */
     protected class ClassReplacements {
-        protected final Map<ResolvedJavaMethod, ResolvedJavaMethod> methodSubstitutions = new HashMap<>();
-        private final Map<ResolvedJavaMethod, Class<? extends FixedWithNextNode>> macroSubstitutions = new HashMap<>();
-        private final Set<ResolvedJavaMethod> forcedSubstitutions = new HashSet<>();
+        public final Map<ResolvedJavaMethod, ResolvedJavaMethod> methodSubstitutions = new HashMap<>();
+        public final Map<ResolvedJavaMethod, Class<? extends FixedWithNextNode>> macroSubstitutions = new HashMap<>();
+        public final Set<ResolvedJavaMethod> forcedSubstitutions = new HashSet<>();
 
         public ClassReplacements(Class<?>[] substitutionClasses, AtomicReference<ClassReplacements> ref) {
             for (Class<?> substitutionClass : substitutionClasses) {
@@ -266,11 +266,15 @@
 
         // Do deferred intrinsification of node intrinsics
 
-        new NodeIntrinsificationPhase(providers, snippetReflection).apply(specializedSnippet);
+        createNodeIntrinsificationPhase().apply(specializedSnippet);
         new CanonicalizerPhase(true).apply(specializedSnippet, new PhaseContext(providers, assumptions));
         NodeIntrinsificationVerificationPhase.verify(specializedSnippet);
     }
 
+    protected NodeIntrinsificationPhase createNodeIntrinsificationPhase() {
+        return new NodeIntrinsificationPhase(providers, snippetReflection);
+    }
+
     @Override
     public StructuredGraph getMethodSubstitution(ResolvedJavaMethod original) {
         ClassReplacements cr = getClassReplacements(original.getDeclaringClass().getName());
@@ -491,7 +495,7 @@
          * Does final processing of a snippet graph.
          */
         protected void finalizeGraph(StructuredGraph graph) {
-            new NodeIntrinsificationPhase(providers, snippetReflection).apply(graph);
+            createNodeIntrinsificationPhase().apply(graph);
             if (!SnippetTemplate.hasConstantParameter(method)) {
                 NodeIntrinsificationVerificationPhase.verify(graph);
             }
@@ -576,6 +580,7 @@
                 } else {
                     createGraphBuilder(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph);
                 }
+                afterParsing(graph);
                 new WordTypeVerificationPhase(metaAccess, snippetReflection, target.wordKind).apply(graph);
                 new WordTypeRewriterPhase(metaAccess, snippetReflection, target.wordKind).apply(graph);
 
@@ -592,6 +597,9 @@
             return new GraphBuilderPhase.Instance(metaAccess, graphBuilderConfig, optimisticOpts);
         }
 
+        protected void afterParsing(@SuppressWarnings("unused") StructuredGraph graph) {
+        }
+
         protected Object beforeInline(@SuppressWarnings("unused") MethodCallTargetNode callTarget, @SuppressWarnings("unused") StructuredGraph callee) {
             return null;
         }
@@ -613,7 +621,7 @@
          * Called after all inlining for a given graph is complete.
          */
         protected void afterInlining(StructuredGraph graph) {
-            new NodeIntrinsificationPhase(providers, snippetReflection).apply(graph);
+            createNodeIntrinsificationPhase().apply(graph);
             new DeadCodeEliminationPhase(Optional).apply(graph);
             if (OptCanonicalizer.getValue()) {
                 new CanonicalizerPhase(true).apply(graph, new PhaseContext(providers, assumptions));
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Sep 17 17:06:37 2014 -0700
@@ -74,12 +74,14 @@
  */
 public class SnippetTemplate {
 
+    public static boolean LAZY_SNIPPETS = true;
+
     /**
      * Holds the {@link ResolvedJavaMethod} of the snippet, together with some information about the
      * method that needs to be computed only once. The {@link SnippetInfo} should be created once
      * per snippet and then cached.
      */
-    public static class SnippetInfo {
+    public abstract static class SnippetInfo {
 
         protected final ResolvedJavaMethod method;
 
@@ -126,8 +128,6 @@
 
         }
 
-        protected final AtomicReference<Lazy> lazy = new AtomicReference<>(null);
-
         /**
          * Times instantiations of all templates derived form this snippet.
          *
@@ -142,12 +142,7 @@
          */
         private final DebugMetric instantiationCounter;
 
-        private Lazy lazy() {
-            if (lazy.get() == null) {
-                lazy.compareAndSet(null, new Lazy(method));
-            }
-            return lazy.get();
-        }
+        protected abstract Lazy lazy();
 
         protected SnippetInfo(ResolvedJavaMethod method) {
             this.method = method;
@@ -192,6 +187,36 @@
         }
     }
 
+    protected static class LazySnippetInfo extends SnippetInfo {
+        protected final AtomicReference<Lazy> lazy = new AtomicReference<>(null);
+
+        protected LazySnippetInfo(ResolvedJavaMethod method) {
+            super(method);
+        }
+
+        @Override
+        protected Lazy lazy() {
+            if (lazy.get() == null) {
+                lazy.compareAndSet(null, new Lazy(method));
+            }
+            return lazy.get();
+        }
+    }
+
+    protected static class EagerSnippetInfo extends SnippetInfo {
+        protected final Lazy lazy;
+
+        protected EagerSnippetInfo(ResolvedJavaMethod method) {
+            super(method);
+            lazy = new Lazy(method);
+        }
+
+        @Override
+        protected Lazy lazy() {
+            return lazy;
+        }
+    }
+
     /**
      * Values that are bound to the snippet method parameters. The methods {@link #add},
      * {@link #addConst}, and {@link #addVarargs} must be called in the same order as in the
@@ -473,7 +498,11 @@
             assert findMethod(declaringClass, methodName, method) == null : "found more than one method named " + methodName + " in " + declaringClass;
             ResolvedJavaMethod javaMethod = providers.getMetaAccess().lookupJavaMethod(method);
             providers.getReplacements().registerSnippet(javaMethod);
-            return new SnippetInfo(javaMethod);
+            if (LAZY_SNIPPETS) {
+                return new LazySnippetInfo(javaMethod);
+            } else {
+                return new EagerSnippetInfo(javaMethod);
+            }
         }
 
         /**
@@ -957,6 +986,10 @@
             // no floating reads yet, ignore locations created while lowering
             return true;
         }
+        if (returnNode == null) {
+            // The snippet terminates control flow
+            return true;
+        }
         MemoryMapNode memoryMap = returnNode.getMemoryMap();
         if (memoryMap == null || memoryMap.isEmpty()) {
             // there are no kills in the snippet graph
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
+
+@NodeInfo
+public class BasicArrayCopyNode extends MacroStateSplitNode implements Virtualizable {
+
+    public static BasicArrayCopyNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new BasicArrayCopyNodeGen(invoke) : new BasicArrayCopyNode(invoke);
+    }
+
+    protected BasicArrayCopyNode(Invoke invoke) {
+        super(invoke);
+    }
+
+    protected ValueNode getSource() {
+        return arguments.get(0);
+    }
+
+    protected ValueNode getSourcePosition() {
+        return arguments.get(1);
+    }
+
+    protected ValueNode getDestination() {
+        return arguments.get(2);
+    }
+
+    protected ValueNode getDestinationPosition() {
+        return arguments.get(3);
+    }
+
+    protected ValueNode getLength() {
+        return arguments.get(4);
+    }
+
+    private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) {
+        return position >= 0 && position + length <= virtualObject.entryCount();
+    }
+
+    private static boolean checkEntryTypes(int srcPos, int length, State srcState, ResolvedJavaType destComponentType, VirtualizerTool tool) {
+        if (destComponentType.getKind() == Kind.Object) {
+            for (int i = 0; i < length; i++) {
+                ValueNode entry = srcState.getEntry(srcPos + i);
+                State state = tool.getObjectState(entry);
+                ResolvedJavaType type;
+                if (state != null) {
+                    if (state.getState() == EscapeState.Virtual) {
+                        type = state.getVirtualObject().type();
+                    } else {
+                        type = StampTool.typeOrNull(state.getMaterializedValue());
+                    }
+                } else {
+                    type = StampTool.typeOrNull(entry);
+                }
+                if (type == null || !destComponentType.isAssignableFrom(type)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        if (getSourcePosition().isConstant() && getDestinationPosition().isConstant() && getLength().isConstant()) {
+            int srcPos = getSourcePosition().asConstant().asInt();
+            int destPos = getDestinationPosition().asConstant().asInt();
+            int length = getLength().asConstant().asInt();
+            State srcState = tool.getObjectState(getSource());
+            State destState = tool.getObjectState(getDestination());
+
+            if (srcState != null && srcState.getState() == EscapeState.Virtual && destState != null && destState.getState() == EscapeState.Virtual) {
+                VirtualObjectNode srcVirtual = srcState.getVirtualObject();
+                VirtualObjectNode destVirtual = destState.getVirtualObject();
+                if (!(srcVirtual instanceof VirtualArrayNode) || !(destVirtual instanceof VirtualArrayNode)) {
+                    return;
+                }
+                if (((VirtualArrayNode) srcVirtual).componentType().getKind() != Kind.Object || ((VirtualArrayNode) destVirtual).componentType().getKind() != Kind.Object) {
+                    return;
+                }
+                if (length < 0 || !checkBounds(srcPos, length, srcVirtual) || !checkBounds(destPos, length, destVirtual)) {
+                    return;
+                }
+                if (!checkEntryTypes(srcPos, length, srcState, destVirtual.type().getComponentType(), tool)) {
+                    return;
+                }
+                for (int i = 0; i < length; i++) {
+                    tool.setVirtualEntry(destState, destPos + i, srcState.getEntry(srcPos + i), false);
+                }
+                tool.delete();
+                if (Debug.isLogEnabled()) {
+                    Debug.log("virtualized arraycopyf(%s, %d, %s, %d, %d)", getSource(), srcPos, getDestination(), destPos, length);
+                }
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java	Wed Sep 17 17:06:37 2014 -0700
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.nodes;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.virtual.*;
+
+@NodeInfo
+public class BasicObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider {
+
+    public static BasicObjectCloneNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new BasicObjectCloneNodeGen(invoke) : new BasicObjectCloneNode(invoke);
+    }
+
+    protected BasicObjectCloneNode(Invoke invoke) {
+        super(invoke);
+    }
+
+    @Override
+    public boolean inferStamp() {
+        return updateStamp(getObject().stamp());
+    }
+
+    public ValueNode getObject() {
+        return arguments.get(0);
+    }
+
+    protected static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) {
+        return metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type);
+    }
+
+    /*
+     * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an
+     * exact type) and if it is a cloneable type.
+     *
+     * If yes, then the exact type is returned, otherwise it returns null.
+     */
+    protected static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) {
+        if (!(stamp instanceof ObjectStamp)) {
+            return null;
+        }
+        ObjectStamp objectStamp = (ObjectStamp) stamp;
+        if (objectStamp.type() == null) {
+            return null;
+        } else if (objectStamp.isExactType()) {
+            return isCloneableType(objectStamp.type(), metaAccess) ? objectStamp.type() : null;
+        } else {
+            ResolvedJavaType type = objectStamp.type().findUniqueConcreteSubtype();
+            if (type != null && isCloneableType(type, metaAccess)) {
+                assumptions.recordConcreteSubtype(objectStamp.type(), type);
+                return type;
+            } else {
+                return null;
+            }
+        }
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        State originalState = tool.getObjectState(getObject());
+        if (originalState != null && originalState.getState() == EscapeState.Virtual) {
+            VirtualObjectNode originalVirtual = originalState.getVirtualObject();
+            if (isCloneableType(originalVirtual.type(), tool.getMetaAccessProvider())) {
+                ValueNode[] newEntryState = new ValueNode[originalVirtual.entryCount()];
+                for (int i = 0; i < newEntryState.length; i++) {
+                    newEntryState[i] = originalState.getEntry(i);
+                }
+                VirtualObjectNode newVirtual = originalVirtual.duplicate();
+                tool.createVirtualObject(newVirtual, newEntryState, Collections.<MonitorIdNode> emptyList());
+                tool.replaceWithVirtual(newVirtual);
+            }
+        } else {
+            ValueNode obj;
+            if (originalState != null) {
+                obj = originalState.getMaterializedValue();
+            } else {
+                obj = tool.getReplacedValue(getObject());
+            }
+            ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions(), tool.getMetaAccessProvider());
+            if (type != null && !type.isArray()) {
+                VirtualInstanceNode newVirtual = createVirtualInstanceNode(type, true);
+                ResolvedJavaField[] fields = newVirtual.getFields();
+
+                ValueNode[] state = new ValueNode[fields.length];
+                final LoadFieldNode[] loads = new LoadFieldNode[fields.length];
+                for (int i = 0; i < fields.length; i++) {
+                    state[i] = loads[i] = LoadFieldNode.create(obj, fields[i]);
+                    tool.addNode(loads[i]);
+                }
+                tool.createVirtualObject(newVirtual, state, Collections.<MonitorIdNode> emptyList());
+                tool.replaceWithVirtual(newVirtual);
+            }
+        }
+    }
+
+    protected VirtualInstanceNode createVirtualInstanceNode(ResolvedJavaType type, boolean hasIdentity) {
+        return VirtualInstanceNode.create(type, hasIdentity);
+    }
+
+    @Override
+    public ValueNode length() {
+        if (getObject() instanceof ArrayLengthProvider) {
+            return ((ArrayLengthProvider) getObject()).length();
+        } else {
+            return null;
+        }
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java	Wed Sep 17 17:06:37 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.truffle.sl.builtins;
 
 import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
@@ -40,6 +41,7 @@
     }
 
     @Specialization
+    @SlowPath
     public String change() {
         FrameInstance frameInstance = Truffle.getRuntime().getCallerFrame();
         Frame frame = frameInstance.getFrame(FrameAccess.READ_WRITE, false);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java	Wed Sep 17 17:06:06 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java	Wed Sep 17 17:06:37 2014 -0700
@@ -52,17 +52,17 @@
         StringBuilder str = new StringBuilder();
 
         Truffle.getRuntime().iterateFrames(frameInstance -> {
-            dumpFrame(str, frameInstance.getCallTarget(), frameInstance.getFrame(FrameAccess.READ_ONLY, true), frameInstance.isVirtualFrame());
+            dumpFrame(str, frameInstance.getCallTarget(), frameInstance.getFrame(FrameAccess.READ_ONLY, true));
             return null;
         });
         return str.toString();
     }
 
-    private static void dumpFrame(StringBuilder str, CallTarget callTarget, Frame frame, boolean isVirtual) {
+    private static void dumpFrame(StringBuilder str, CallTarget callTarget, Frame frame) {
         if (str.length() > 0) {
             str.append("\n");
         }
-        str.append("Frame: ").append(callTarget).append(isVirtual ? " (virtual)" : "");
+        str.append("Frame: ").append(((RootCallTarget) callTarget).getRootNode().toString());
         FrameDescriptor frameDescriptor = frame.getFrameDescriptor();
         for (FrameSlot s : frameDescriptor.getSlots()) {
             str.append(", ").append(s.getIdentifier()).append("=").append(frame.getValue(s));