changeset 14826:17a735726670

Merge.
author Josef Eisl <josef.eisl@jku.at>
date Thu, 20 Mar 2014 13:50:21 +0100
parents 5ddfdc13027a (current diff) da2431cc1506 (diff)
children 2ed3233503b8
files graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/Marks.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java mx/projects
diffstat 214 files changed, 3647 insertions(+), 1651 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Wed Mar 19 19:02:29 2014 +0100
+++ b/CHANGELOG.md	Thu Mar 20 13:50:21 2014 +0100
@@ -7,7 +7,22 @@
 * Made graph caching compilation-local.
 
 ### Truffle
-* ...
+* New API TruffleRuntime#createCallNode to create call nodes and to give the runtime system control over its implementation.
+* New API RootNode#getCachedCallNodes to get a weak set of CallNodes that have registered to call the RootNode.
+* New API to split the AST of a call-site context sensitively. CallNode#split, CallNode#isSplittable, CallNode#getSplitCallTarget, CallNode#getCurrentCallTarget, RootNode#isSplittable, RootNode#split.
+* New API to inline a call-site into the call-graph. CallNode#isInlinable, CallNode#inline, CallNode#isInlined.
+* New API for the runtime environment to register CallTargets as caller to the RootNode. CallNode#registerCallTarget.
+* Improved API for counting nodes in Truffle ASTS. NodeUtil#countNodes can be used with a NodeFilter filter Nodes.
+* New API to declare the cost of a Node for use in runtime environment specific heuristics. See NodeCost, Node#getCost() and NodeInfo#cost().
+* Removed old API for NodeInfo#Kind and NodeInfo#kind(). As a replacement the new Node cost API can be used.
+* Changed Node#replace reason parameter type to CharSequence (to allow for lazy string building)
+* Deprecated Node#adoptChild and Node#adoptChild, no longer needed in node constructor
+* New Node#insert method for inserting new nodes into the tree (formerly adoptChild)
+* New Node#adoptChildren() helper method that adopts all (direct and indirect) children of a node
+* New API Node#atomic for atomic tree operations
+* Made Node#replace thread-safe
+
+
 
 ## Version 0.1
 5-Feb-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/b124e22eb772)
--- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java	Thu Mar 20 13:50:21 2014 +0100
@@ -146,7 +146,6 @@
                 case Short:
                 case Int:
                 case Long:
-                case NarrowOop:
                 case Object:
                     return true;
             }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Thu Mar 20 13:50:21 2014 +0100
@@ -198,8 +198,6 @@
                 return 8;
             case Object:
                 return wordSize;
-            case NarrowOop:
-                return wordSize / 2;
             default:
                 return 0;
         }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java	Thu Mar 20 13:50:21 2014 +0100
@@ -71,7 +71,7 @@
      *            CSA
      * @param registers the registers that can be saved in the CSA
      */
-    public CalleeSaveLayout(Architecture architecture, int frameOffsetToCSA, int size, int slotSize, Register... registers) {
+    public CalleeSaveLayout(TargetDescription target, int frameOffsetToCSA, int size, int slotSize, Register... registers) {
         this.frameOffsetToCSA = frameOffsetToCSA;
         assert slotSize == 0 || CodeUtil.isPowerOf2(slotSize);
         this.slotSize = slotSize;
@@ -88,8 +88,8 @@
             if (offset > maxOffset) {
                 maxOffset = offset;
             }
-            PlatformKind kind = architecture.getLargestStorableKind(reg.getRegisterCategory());
-            offset += architecture.getSizeInBytes(kind);
+            PlatformKind kind = target.arch.getLargestStorableKind(reg.getRegisterCategory());
+            offset += target.getSizeInBytes(kind);
         }
         if (size == -1) {
             this.size = offset;
@@ -106,8 +106,8 @@
             int index = offset / slotSize;
             regNumToIndex[reg.number] = index;
             indexToReg[index] = reg;
-            PlatformKind kind = architecture.getLargestStorableKind(reg.getRegisterCategory());
-            offset += architecture.getSizeInBytes(kind);
+            PlatformKind kind = target.arch.getLargestStorableKind(reg.getRegisterCategory());
+            offset += target.getSizeInBytes(kind);
         }
     }
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Thu Mar 20 13:50:21 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.api.code;
 
+import com.oracle.graal.api.code.CompilationResult.Data;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.meta.*;
 
@@ -85,6 +86,11 @@
     boolean needsDataPatch(Constant constant);
 
     /**
+     * Create a {@link Data} item for a {@link Constant}, that can be used in a {@link DataPatch}.
+     */
+    Data createDataItem(Constant constant, int alignment);
+
+    /**
      * Gets a description of the target architecture.
      */
     TargetDescription getTarget();
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Thu Mar 20 13:50:21 2014 +0100
@@ -281,6 +281,17 @@
         }
     }
 
+    public static class NumberedRefMapFormatter implements RefMapFormatter {
+
+        public String formatStackSlot(int frameRefMapIndex) {
+            return "s" + frameRefMapIndex;
+        }
+
+        public String formatRegister(int regRefMapIndex) {
+            return "r" + regRefMapIndex;
+        }
+    }
+
     /**
      * Appends a formatted debug info to a {@link StringBuilder}.
      * 
@@ -288,7 +299,11 @@
      * @param info the debug info to format and append to {@code sb}
      * @return the value of {@code sb}
      */
-    public static StringBuilder append(StringBuilder sb, DebugInfo info, RefMapFormatter formatter) {
+    public static StringBuilder append(StringBuilder sb, DebugInfo info, RefMapFormatter formatterArg) {
+        RefMapFormatter formatter = formatterArg;
+        if (formatter == null) {
+            formatter = new NumberedRefMapFormatter();
+        }
         String nl = NEW_LINE;
         ReferenceMap refMap = info.getReferenceMap();
         if (refMap != null && refMap.hasRegisterRefMap()) {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Thu Mar 20 13:50:21 2014 +0100
@@ -28,6 +28,7 @@
 import java.nio.*;
 import java.util.*;
 
+import com.oracle.graal.api.code.CodeUtil.*;
 import com.oracle.graal.api.meta.*;
 
 /**
@@ -152,66 +153,64 @@
             return alignment;
         }
 
-        public abstract int getSize(Architecture arch);
+        public abstract int getSize(TargetDescription target);
 
-        public abstract void emit(Architecture arch, ByteBuffer buffer);
+        public abstract Kind getKind();
+
+        public abstract void emit(TargetDescription target, ByteBuffer buffer);
     }
 
-    public static final class ConstantData extends Data {
+    /**
+     * Represents a Java primitive value used in a {@link DataPatch}. This implementation uses
+     * {@link Kind#getByteCount()} bytes to encode each value.
+     */
+    public static final class PrimitiveData extends Data {
 
         public final Constant constant;
 
-        public ConstantData(Constant constant, int alignment) {
+        public PrimitiveData(Constant constant, int alignment) {
             super(alignment);
+            assert constant.getKind().isPrimitive();
             this.constant = constant;
         }
 
         @Override
-        public int getSize(Architecture arch) {
-            return arch.getSizeInBytes(constant.getPlatformKind());
+        public int getSize(TargetDescription target) {
+            return constant.getKind().getByteCount();
+        }
+
+        @Override
+        public Kind getKind() {
+            return constant.getKind();
         }
 
         @Override
-        public void emit(Architecture arch, ByteBuffer buffer) {
+        public void emit(TargetDescription target, ByteBuffer buffer) {
             switch (constant.getKind()) {
                 case Boolean:
-                    assert getSize(arch) == 1;
                     buffer.put(constant.asBoolean() ? (byte) 1 : (byte) 0);
                     break;
                 case Byte:
-                    assert getSize(arch) == 1;
                     buffer.put((byte) constant.asInt());
                     break;
                 case Char:
-                    assert getSize(arch) == 2;
                     buffer.putChar((char) constant.asInt());
                     break;
                 case Short:
-                    assert getSize(arch) == 2;
                     buffer.putShort((short) constant.asInt());
                     break;
                 case Int:
-                    assert getSize(arch) == 4;
                     buffer.putInt(constant.asInt());
                     break;
                 case Long:
-                    assert getSize(arch) == 8;
                     buffer.putLong(constant.asLong());
                     break;
                 case Float:
-                    assert getSize(arch) == 4;
                     buffer.putFloat(constant.asFloat());
                     break;
                 case Double:
-                    assert getSize(arch) == 8;
                     buffer.putDouble(constant.asDouble());
                     break;
-                case Object:
-                    // placeholder for oop value
-                    for (int i = 0; i < getSize(arch); i++) {
-                        buffer.put((byte) 0);
-                    }
-                    break;
             }
         }
 
@@ -219,6 +218,24 @@
         public String toString() {
             return constant.toString();
         }
+
+        @Override
+        public int hashCode() {
+            return constant.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj instanceof PrimitiveData) {
+                PrimitiveData other = (PrimitiveData) obj;
+                return constant.equals(other.constant);
+            } else {
+                return false;
+            }
+        }
     }
 
     public static final class RawData extends Data {
@@ -231,12 +248,17 @@
         }
 
         @Override
-        public int getSize(Architecture arch) {
+        public int getSize(TargetDescription target) {
             return data.length;
         }
 
         @Override
-        public void emit(Architecture arch, ByteBuffer buffer) {
+        public Kind getKind() {
+            return Kind.Illegal;
+        }
+
+        @Override
+        public void emit(TargetDescription target, ByteBuffer buffer) {
             buffer.put(data);
         }
 
@@ -250,6 +272,24 @@
             }
             return ret.toString();
         }
+
+        @Override
+        public int hashCode() {
+            return Arrays.hashCode(data);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj instanceof RawData) {
+                RawData other = (RawData) obj;
+                return Arrays.equals(data, other.data);
+            } else {
+                return false;
+            }
+        }
     }
 
     /**
@@ -260,53 +300,18 @@
     public static final class DataPatch extends Site {
 
         private static final long serialVersionUID = 5771730331604867476L;
-        public Data externalData;
-        public Constant inlineData;
-
-        DataPatch(int pcOffset, Data externalData) {
-            this(pcOffset, externalData, null);
-        }
-
-        DataPatch(int pcOffset, Constant inlineData) {
-            this(pcOffset, null, inlineData);
-        }
-
-        private DataPatch(int pcOffset, Data externalData, Constant inlineData) {
-            super(pcOffset);
-            assert (externalData == null) != (inlineData == null) : "data patch can not be both external and inlined";
-            this.externalData = externalData;
-            this.inlineData = inlineData;
-        }
+        public Data data;
+        public boolean inline;
 
-        public Constant getConstant() {
-            if (inlineData != null) {
-                return inlineData;
-            } else if (externalData instanceof ConstantData) {
-                return ((ConstantData) externalData).constant;
-            } else {
-                return null;
-            }
-        }
-
-        public int getAlignment() {
-            if (externalData instanceof ConstantData) {
-                return ((ConstantData) externalData).getAlignment();
-            } else {
-                return 0;
-            }
-        }
-
-        public String getDataString() {
-            if (inlineData != null) {
-                return inlineData.toString();
-            } else {
-                return externalData.toString();
-            }
+        public DataPatch(int pcOffset, Data data, boolean inline) {
+            super(pcOffset);
+            this.data = data;
+            this.inline = inline;
         }
 
         @Override
         public String toString() {
-            return String.format("%d[<data patch referring to data %s>]", pcOffset, getDataString());
+            return String.format("%d[<data patch referring to %s data %s>]", pcOffset, inline ? "inline" : "external", data.toString());
         }
     }
 
@@ -538,18 +543,18 @@
      */
     public void recordDataReference(int codePos, Data data) {
         assert codePos >= 0 && data != null;
-        dataReferences.add(new DataPatch(codePos, data));
+        dataReferences.add(new DataPatch(codePos, data, false));
     }
 
     /**
      * Records a reference to an inlined constant in the code section (e.g. to load a constant oop).
      * 
      * @param codePos the position in the code where the inlined constant occurs
-     * @param constant the constant that is referenced
+     * @param data the data that is referenced
      */
-    public void recordInlineData(int codePos, Constant constant) {
-        assert codePos >= 0 && constant != null;
-        dataReferences.add(new DataPatch(codePos, constant));
+    public void recordInlineData(int codePos, Data data) {
+        assert codePos >= 0 && data != null;
+        dataReferences.add(new DataPatch(codePos, data, true));
     }
 
     /**
@@ -691,14 +696,15 @@
         if (info != null) {
             ReferenceMap refMap = info.getReferenceMap();
             if (refMap != null) {
+                RefMapFormatter formatter = new CodeUtil.NumberedRefMapFormatter();
                 if (refMap.hasFrameRefMap()) {
                     sb.append(" stackMap[");
-                    refMap.appendFrameMap(sb, null);
+                    refMap.appendFrameMap(sb, formatter);
                     sb.append(']');
                 }
                 if (refMap.hasRegisterRefMap()) {
                     sb.append(" registerMap[");
-                    refMap.appendRegisterMap(sb, null);
+                    refMap.appendRegisterMap(sb, formatter);
                     sb.append(']');
                 }
             }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java	Thu Mar 20 13:50:21 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -22,123 +22,20 @@
  */
 package com.oracle.graal.api.code;
 
-import java.io.*;
-import java.util.*;
-
 import com.oracle.graal.api.code.CodeUtil.RefMapFormatter;
-
-public class ReferenceMap implements Serializable {
-
-    private static final long serialVersionUID = -1052183095979496819L;
-
-    /**
-     * Contains 2 bits per register.
-     * <ul>
-     * <li>bit0 = 0: contains no references</li>
-     * <li>bit0 = 1, bit1 = 0: contains a wide oop</li>
-     * <li>bit0 = 1, bit1 = 1: contains a narrow oop</li>
-     * </ul>
-     */
-    private final BitSet registerRefMap;
-
-    /**
-     * Contains 3 bits per stack slot.
-     * <ul>
-     * <li>bit0 = 0: contains no references</li>
-     * <li>bit0 = 1, bit1+2 = 0: contains a wide oop</li>
-     * <li>bit0 = 1, bit1 = 1: contains a narrow oop in the lower half</li>
-     * <li>bit0 = 1, bit2 = 1: contains a narrow oop in the upper half</li>
-     * </ul>
-     */
-    private final BitSet frameRefMap;
+import com.oracle.graal.api.meta.*;
 
-    public ReferenceMap(int registerCount, int frameSlotCount) {
-        if (registerCount > 0) {
-            this.registerRefMap = new BitSet(registerCount * 2);
-        } else {
-            this.registerRefMap = null;
-        }
-        this.frameRefMap = new BitSet(frameSlotCount * 3);
-    }
+public interface ReferenceMap {
 
-    public void setRegister(int idx, boolean narrow) {
-        registerRefMap.set(2 * idx);
-        if (narrow) {
-            registerRefMap.set(2 * idx + 1);
-        }
-    }
+    void setRegister(int idx, PlatformKind kind);
 
-    public void setStackSlot(int idx, boolean narrow1, boolean narrow2) {
-        frameRefMap.set(3 * idx);
-        if (narrow1) {
-            frameRefMap.set(3 * idx + 1);
-        }
-        if (narrow2) {
-            frameRefMap.set(3 * idx + 2);
-        }
-    }
-
-    public boolean hasRegisterRefMap() {
-        return registerRefMap != null && registerRefMap.size() > 0;
-    }
+    void setStackSlot(int offset, PlatformKind kind);
 
-    public boolean hasFrameRefMap() {
-        return frameRefMap != null && frameRefMap.size() > 0;
-    }
-
-    public interface Iterator {
-        void register(int idx, boolean narrow);
-
-        void stackSlot(int idx, boolean narrow1, boolean narrow2);
-    }
+    boolean hasRegisterRefMap();
 
-    public void iterate(Iterator iterator) {
-        if (hasRegisterRefMap()) {
-            for (int i = 0; i < registerRefMap.size() / 2; i++) {
-                if (registerRefMap.get(2 * i)) {
-                    iterator.register(i, registerRefMap.get(2 * i + 1));
-                }
-            }
-        }
-        if (hasFrameRefMap()) {
-            for (int i = 0; i < frameRefMap.size() / 3; i++) {
-                if (frameRefMap.get(3 * i)) {
-                    iterator.stackSlot(i, frameRefMap.get(3 * i + 1), frameRefMap.get(3 * i + 2));
-                }
-            }
-        }
-    }
-
-    private static class NumberedRefMapFormatter implements RefMapFormatter {
+    boolean hasFrameRefMap();
 
-        public String formatStackSlot(int frameRefMapIndex) {
-            return "s" + frameRefMapIndex;
-        }
-
-        public String formatRegister(int regRefMapIndex) {
-            return "r" + regRefMapIndex;
-        }
-    }
-
-    public void appendRegisterMap(StringBuilder sb, RefMapFormatter formatterArg) {
-        RefMapFormatter formatter = formatterArg;
-        if (formatter == null) {
-            formatter = new NumberedRefMapFormatter();
-        }
+    void appendRegisterMap(StringBuilder sb, RefMapFormatter formatterArg);
 
-        for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 2)) {
-            sb.append(' ').append(formatter.formatRegister(reg / 2));
-        }
-    }
-
-    public void appendFrameMap(StringBuilder sb, RefMapFormatter formatterArg) {
-        RefMapFormatter formatter = formatterArg;
-        if (formatter == null) {
-            formatter = new NumberedRefMapFormatter();
-        }
-
-        for (int slot = frameRefMap.nextSetBit(0); slot >= 0; slot = frameRefMap.nextSetBit(slot + 3)) {
-            sb.append(' ').append(formatter.formatStackSlot(slot / 3));
-        }
-    }
+    void appendFrameMap(StringBuilder sb, RefMapFormatter formatterArg);
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java	Thu Mar 20 13:50:21 2014 +0100
@@ -102,4 +102,10 @@
      * @return the register playing the role specified by {@code id}
      */
     Register getRegisterForRole(int id);
+
+    /**
+     * Determines if all {@link #getAllocatableRegisters() allocatable} registers are
+     * {@link #getCallerSaveRegisters() caller saved}.
+     */
+    boolean areAllAllocatableRegistersCallerSaved();
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java	Thu Mar 20 13:50:21 2014 +0100
@@ -28,7 +28,7 @@
  * Represents the target machine for a compiler, including the CPU architecture, the size of
  * pointers and references, alignment of stacks, caches, etc.
  */
-public class TargetDescription {
+public abstract class TargetDescription {
 
     public final Architecture arch;
 
@@ -81,4 +81,10 @@
         this.implicitNullCheckLimit = implicitNullCheckLimit;
         this.inlineObjects = inlineObjects;
     }
+
+    public int getSizeInBytes(PlatformKind kind) {
+        return arch.getSizeInBytes(kind);
+    }
+
+    public abstract ReferenceMap createReferenceMap(boolean hasRegisters, int stackSlotCount);
 }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Thu Mar 20 13:50:21 2014 +0100
@@ -77,22 +77,6 @@
         }
     }
 
-    /**
-     * @see ResolvedJavaMethod#getCompiledCodeSize()
-     */
-    @Test
-    public void getCompiledCodeSizeTest() {
-        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
-            ResolvedJavaMethod m = e.getValue();
-            int size = m.getCompiledCodeSize();
-            if (isAbstract(m.getModifiers())) {
-                assertTrue(size == 0);
-            } else {
-                assertTrue(size >= 0);
-            }
-        }
-    }
-
     @Test
     public void getModifiersTest() {
         for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Thu Mar 20 13:50:21 2014 +0100
@@ -159,7 +159,6 @@
             case Double:
                 return asDouble();
             case Object:
-            case NarrowOop:
                 return object;
             case Illegal:
                 return this;
@@ -172,7 +171,7 @@
         if (!ignoreKind && getKind() != other.getKind()) {
             return false;
         }
-        if (getKind() == Kind.Object || getKind() == Kind.NarrowOop) {
+        if (getKind() == Kind.Object) {
             return object == other.object;
         }
         return primitive == other.primitive && getPrimitiveAnnotation() == other.getPrimitiveAnnotation();
@@ -235,12 +234,12 @@
 
     /**
      * Returns the object reference this constant represents. The constant must have kind
-     * {@link Kind#Object} or {@link Kind#NarrowOop}.
+     * {@link Kind#Object}.
      * 
      * @return the constant value
      */
     public Object asObject() {
-        assert getKind() == Kind.Object || getKind() == Kind.NarrowOop;
+        assert getKind() == Kind.Object;
         return object;
     }
 
@@ -250,7 +249,7 @@
      * @return null if this constant is not primitive or has no annotation
      */
     public Object getPrimitiveAnnotation() {
-        return getKind() == Kind.Object || getKind() == Kind.NarrowOop ? null : object;
+        return getKind() == Kind.Object ? null : object;
     }
 
     /**
@@ -260,7 +259,7 @@
      */
     @Override
     public int hashCode() {
-        if (getKind() == Kind.Object || getKind() == Kind.NarrowOop) {
+        if (getKind() == Kind.Object) {
             return System.identityHashCode(object);
         }
         return (int) primitive * getKind().ordinal();
@@ -394,16 +393,6 @@
     }
 
     /**
-     * Creates a boxed narrow oop constant.
-     * 
-     * @param o the object value to box
-     * @return a boxed copy of {@code value}
-     */
-    public static Constant forNarrowOop(Object o) {
-        return new Constant(Kind.NarrowOop, o, 0L);
-    }
-
-    /**
      * Creates an annotated int or long constant. An annotation enables a client to associate some
      * extra semantic or debugging information with a primitive. An annotated primitive constant is
      * never {@linkplain #equals(Object) equal} to a non-annotated constant.
@@ -463,8 +452,6 @@
                 return forDouble((Double) value);
             case Object:
                 return forObject(value);
-            case NarrowOop:
-                return forNarrowOop(value);
             default:
                 throw new RuntimeException("cannot create Constant for boxed " + kind + " value");
         }
@@ -497,8 +484,6 @@
                 return LONG_0;
             case Object:
                 return NULL_OBJECT;
-            case NarrowOop:
-                return forNarrowOop(null);
             default:
                 throw new IllegalArgumentException(kind.toString());
         }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java	Thu Mar 20 13:50:21 2014 +0100
@@ -99,4 +99,12 @@
     public void setMature() {
         // Do nothing
     }
+
+    public boolean setCompilerIRSize(Class<?> irType, int nodeCount) {
+        return false;
+    }
+
+    public int getCompilerIRSize(Class<?> irType) {
+        return -1;
+    }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Thu Mar 20 13:50:21 2014 +0100
@@ -57,9 +57,6 @@
     /** The Object kind, also used for arrays. */
     Object('a', "Object", false, null, null),
 
-    /** The narrow oop kind. */
-    NarrowOop('n', "NarrowOop", false, null, null),
-
     /** The void float kind. */
     Void('v', "void", false, java.lang.Void.TYPE, java.lang.Void.class),
 
@@ -149,10 +146,10 @@
     /**
      * Checks whether this represent an Object of some sort.
      * 
-     * @return {@code true} if this is {@link #Object} or {@link #NarrowOop}.
+     * @return {@code true} if this is {@link #Object}.
      */
     public boolean isObject() {
-        return this == Kind.Object || this == Kind.NarrowOop;
+        return this == Kind.Object;
     }
 
     /**
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ObjectLocationIdentity.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ObjectLocationIdentity.java	Thu Mar 20 13:50:21 2014 +0100
@@ -25,7 +25,7 @@
 import java.util.*;
 
 /**
- * A {@link LocationIdentity} warpping an object.
+ * A {@link LocationIdentity} wrapping an object.
  */
 public final class ObjectLocationIdentity implements LocationIdentity {
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Thu Mar 20 13:50:21 2014 +0100
@@ -114,6 +114,25 @@
     int getDeoptimizationCount(DeoptimizationReason reason);
 
     /**
+     * Records the size of the compiler intermediate representation (IR) associated with this
+     * method.
+     * 
+     * @param irType the IR type for which the size is being recorded
+     * @param irSize the IR size to be recorded. The unit depends on the IR.
+     * @return whether recording this information for {@code irType} is supported
+     */
+    boolean setCompilerIRSize(Class<?> irType, int irSize);
+
+    /**
+     * Gets the size of the compiler intermediate representation (IR) associated with this method
+     * last recorded by {@link #setCompilerIRSize(Class, int)}.
+     * 
+     * @param irType the IR type for which the size is being requested
+     * @return the requested IR size or -1 if it is unavailable for {@code irType}
+     */
+    int getCompilerIRSize(Class<?> irType);
+
+    /**
      * Returns true if the profiling information can be assumed as sufficiently accurate.
      * 
      * @return true if the profiling information was recorded often enough mature enough, false
@@ -124,6 +143,5 @@
     /**
      * Force data to be treated as mature if possible.
      */
-
     void setMature();
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Thu Mar 20 13:50:21 2014 +0100
@@ -24,7 +24,6 @@
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
-import java.util.*;
 
 /**
  * Represents a resolved Java method. Methods, like fields and types, are resolved through
@@ -54,13 +53,6 @@
     int getCodeSize();
 
     /**
-     * Returns the size of the compiled machine code of this method.
-     * 
-     * @return the size of the compiled machine code in bytes, or 0 if no compiled code exists.
-     */
-    int getCompiledCodeSize();
-
-    /**
      * Returns the {@link ResolvedJavaType} object representing the class or interface that declares
      * this method.
      */
@@ -144,12 +136,6 @@
     void reprofile();
 
     /**
-     * Returns a map that the compiler can use to store objects that should survive the current
-     * compilation.
-     */
-    Map<Object, Object> getCompilerStorage();
-
-    /**
      * Returns the constant pool of this method.
      */
     ConstantPool getConstantPool();
--- a/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -27,7 +27,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CompilationResult.ConstantData;
+import com.oracle.graal.api.code.CompilationResult.PrimitiveData;
 import com.oracle.graal.api.code.CompilationResult.RawData;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
@@ -59,7 +59,7 @@
             public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) {
                 AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig);
                 Register ret = registerConfig.getReturnRegister(Kind.Double);
-                compResult.recordDataReference(asm.position(), new ConstantData(Constant.forDouble(84.72), 8));
+                compResult.recordDataReference(asm.position(), new PrimitiveData(Constant.forDouble(84.72), 8));
                 asm.movdbl(ret, asm.getPlaceholder());
                 asm.ret(0);
                 return asm.close(true);
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java	Thu Mar 20 13:50:21 2014 +0100
@@ -261,7 +261,7 @@
     private AMD64Address trigPrologue(Register value) {
         assert value.getRegisterCategory() == AMD64.XMM;
         AMD64Address tmp = new AMD64Address(AMD64.rsp);
-        subq(AMD64.rsp, target.arch.getSizeInBytes(Kind.Double));
+        subq(AMD64.rsp, target.getSizeInBytes(Kind.Double));
         movdbl(tmp, value);
         fldd(tmp);
         return tmp;
@@ -271,7 +271,7 @@
         assert dest.getRegisterCategory() == AMD64.XMM;
         fstpd(tmp);
         movdbl(dest, tmp);
-        addq(AMD64.rsp, target.arch.getSizeInBytes(Kind.Double));
+        addq(AMD64.rsp, target.getSizeInBytes(Kind.Double));
     }
 
     /**
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Thu Mar 20 13:50:21 2014 +0100
@@ -264,9 +264,6 @@
             case Byte:
                 prefix = "s8";
                 break;
-            case NarrowOop:
-                prefix = "u32";
-                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Mar 20 13:50:21 2014 +0100
@@ -360,9 +360,9 @@
     }
 
     @Override
-    public void emitNullCheck(ValueNode v, DeoptimizingNode deoping) {
-        assert v.stamp() instanceof ObjectStamp;
-        append(new AMD64Move.NullCheckOp(load(operand(v)), state(deoping)));
+    public void emitNullCheck(ValueNode v, DeoptimizingNode deopt) {
+        assert v.getKind() == Kind.Object : v + " - " + v.stamp() + " @ " + deopt;
+        append(new AMD64Move.NullCheckOp(load(operand(v)), state(deopt)));
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/AllocSpy.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2011, 2014, 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.test;
+
+import static java.lang.Boolean.*;
+import static java.lang.Integer.*;
+import static java.lang.System.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.google.monitoring.runtime.instrumentation.*;
+
+/**
+ * Tool for analyzing allocations within a scope using the <a
+ * href="https://code.google.com/p/java-allocation-instrumenter/">Java Allocation Instrumenter</a>.
+ * Allocation records are aggregated per stack trace at an allocation site. The size of the stack
+ * trace is governed by the value of the "AllocSpy.ContextSize" system property (default is 5).
+ * <p>
+ * Using this facility requires using -javaagent on the command line. For example:
+ * 
+ * <pre>
+ * mx --vm server unittest -javaagent:lib/java-allocation-instrumenter.jar -dsa -DAllocSpy.ContextSize=6 BC_iadd2
+ * </pre>
+ * 
+ * @see #SampleBytes
+ * @see #SampleInstances
+ * @see #HistogramLimit
+ * @see #NameSize
+ * @see #BarSize
+ * @see #NumberSize
+ */
+final class AllocSpy implements AutoCloseable {
+
+    static ThreadLocal<AllocSpy> current = new ThreadLocal<>();
+
+    private static final boolean ENABLED;
+    static {
+        boolean enabled = false;
+        try {
+            Field field = AllocationRecorder.class.getDeclaredField("instrumentation");
+            field.setAccessible(true);
+            enabled = field.get(null) != null;
+        } catch (Exception e) {
+        }
+        ENABLED = enabled;
+        if (ENABLED) {
+            AllocationRecorder.addSampler(new GraalContextSampler());
+        }
+    }
+
+    static String prop(String sfx) {
+        return AllocSpy.class.getSimpleName() + "." + sfx;
+    }
+
+    /**
+     * Determines if bytes per allocation site are recorded.
+     */
+    private static final boolean SampleBytes = parseBoolean(getProperty(prop("SampleBytes"), "true"));
+
+    /**
+     * Determines if allocations per allocation site are recorded.
+     */
+    private static final boolean SampleInstances = parseBoolean(getProperty(prop("SampleInstances"), "true"));
+
+    /**
+     * The size of context to record for each allocation site in terms of Graal frames.
+     */
+    private static final int ContextSize = getInteger(prop("ContextSize"), 5);
+
+    /**
+     * Only the {@code HistogramLimit} most frequent values are printed.
+     */
+    private static final int HistogramLimit = getInteger(prop("HistogramLimit"), 40);
+
+    /**
+     * The width of the allocation context column.
+     */
+    private static final int NameSize = getInteger(prop("NameSize"), 50);
+
+    /**
+     * The width of the histogram bar column.
+     */
+    private static final int BarSize = getInteger(prop("BarSize"), 100);
+
+    /**
+     * The width of the frequency column.
+     */
+    private static final int NumberSize = getInteger(prop("NumberSize"), 10);
+
+    final Object name;
+    final AllocSpy parent;
+    final Map<String, CountedValue> bytesPerGraalContext = new HashMap<>();
+    final Map<String, CountedValue> instancesPerGraalContext = new HashMap<>();
+
+    public static AllocSpy open(Object name) {
+        if (ENABLED) {
+            return new AllocSpy(name);
+        }
+        return null;
+    }
+
+    private AllocSpy(Object name) {
+        this.name = name;
+        parent = current.get();
+        current.set(this);
+    }
+
+    public void close() {
+        current.set(parent);
+        PrintStream ps = System.out;
+        ps.println("\n\nAllocation histograms for " + name);
+        if (SampleBytes) {
+            print(ps, bytesPerGraalContext, "BytesPerGraalContext", HistogramLimit, NameSize + 60, BarSize);
+        }
+        if (SampleInstances) {
+            print(ps, instancesPerGraalContext, "InstancesPerGraalContext", HistogramLimit, NameSize + 60, BarSize);
+        }
+    }
+
+    private static void printLine(PrintStream printStream, char c, int lineSize) {
+        char[] charArr = new char[lineSize];
+        Arrays.fill(charArr, c);
+        printStream.printf("%s%n", new String(charArr));
+    }
+
+    private static void print(PrintStream ps, Map<String, CountedValue> map, String name, int limit, int nameSize, int barSize) {
+        if (map.isEmpty()) {
+            return;
+        }
+
+        List<CountedValue> list = new ArrayList<>(map.values());
+        Collections.sort(list);
+
+        // Sum up the total number of elements.
+        int total = 0;
+        for (CountedValue cv : list) {
+            total += cv.getCount();
+        }
+
+        // Print header.
+        ps.printf("%s has %d unique elements and %d total elements:%n", name, list.size(), total);
+
+        int max = list.get(0).getCount();
+        final int lineSize = nameSize + NumberSize + barSize + 10;
+        printLine(ps, '-', lineSize);
+        String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n";
+        for (int i = 0; i < list.size() && i < limit; ++i) {
+            CountedValue cv = list.get(i);
+            int value = cv.getCount();
+            char[] bar = new char[(int) (((double) value / (double) max) * barSize)];
+            Arrays.fill(bar, '=');
+            String[] lines = String.valueOf(cv.getValue()).split("\\n");
+
+            String objectString = lines[0];
+            if (objectString.length() > nameSize) {
+                objectString = objectString.substring(0, nameSize - 3) + "...";
+            }
+            ps.printf(formatString, objectString, value, new String(bar));
+            for (int j = 1; j < lines.length; j++) {
+                String line = lines[j];
+                if (line.length() > nameSize) {
+                    line = line.substring(0, nameSize - 3) + "...";
+                }
+                ps.printf("|   %-" + (nameSize - 2) + "s | %-" + NumberSize + "s | %-" + barSize + "s |%n", line, " ", " ");
+
+            }
+        }
+        printLine(ps, '-', lineSize);
+    }
+
+    CountedValue bytesPerGraalContext(String context) {
+        return getCounter(context, bytesPerGraalContext);
+    }
+
+    CountedValue instancesPerGraalContext(String context) {
+        return getCounter(context, instancesPerGraalContext);
+    }
+
+    protected static CountedValue getCounter(String desc, Map<String, CountedValue> map) {
+        CountedValue count = map.get(desc);
+        if (count == null) {
+            count = new CountedValue(0, desc);
+            map.put(desc, count);
+        }
+        return count;
+    }
+
+    private static final String[] Excluded = {AllocSpy.class.getName(), AllocationRecorder.class.getName()};
+
+    private static boolean excludeFrame(String className) {
+        for (String e : Excluded) {
+            if (className.startsWith(e)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static class GraalContextSampler implements Sampler {
+
+        public void sampleAllocation(int count, String desc, Object newObj, long size) {
+            AllocSpy scope = current.get();
+            if (scope != null) {
+                StringBuilder sb = new StringBuilder(200);
+                Throwable t = new Throwable();
+                int remainingGraalFrames = ContextSize;
+                for (StackTraceElement e : t.getStackTrace()) {
+                    if (remainingGraalFrames < 0) {
+                        break;
+                    }
+                    String className = e.getClassName();
+                    boolean isGraalFrame = className.contains(".graal.");
+                    if (sb.length() != 0) {
+                        append(sb.append('\n'), e);
+                    } else {
+                        if (!excludeFrame(className)) {
+                            sb.append("type=").append(desc);
+                            if (count != 1) {
+                                sb.append("[]");
+                            }
+                            append(sb.append('\n'), e);
+                        }
+                    }
+                    if (isGraalFrame) {
+                        remainingGraalFrames--;
+                    }
+                }
+                String context = sb.toString();
+                if (SampleBytes) {
+                    scope.bytesPerGraalContext(context).add((int) size);
+                }
+                if (SampleInstances) {
+                    scope.instancesPerGraalContext(context).inc();
+                }
+            }
+        }
+
+        protected StringBuilder append(StringBuilder sb, StackTraceElement e) {
+            String className = e.getClassName();
+            int period = className.lastIndexOf('.');
+            if (period != -1) {
+                sb.append(className, period + 1, className.length());
+            } else {
+                sb.append(className);
+            }
+            sb.append('.').append(e.getMethodName());
+            if (e.isNativeMethod()) {
+                sb.append("(Native Method)");
+            } else if (e.getFileName() != null && e.getLineNumber() >= 0) {
+                sb.append('(').append(e.getFileName()).append(':').append(e.getLineNumber()).append(")");
+            } else {
+                sb.append("(Unknown Source)");
+            }
+            return sb;
+        }
+    }
+
+    /**
+     * A value and a frequency. The ordering imposed by {@link #compareTo(CountedValue)} places
+     * values with higher frequencies first.
+     */
+    static class CountedValue implements Comparable<CountedValue> {
+
+        private int count;
+        private final Object value;
+
+        public CountedValue(int count, Object value) {
+            this.count = count;
+            this.value = value;
+        }
+
+        public int compareTo(CountedValue o) {
+            if (count < o.count) {
+                return 1;
+            } else if (count > o.count) {
+                return -1;
+            }
+            return 0;
+        }
+
+        @Override
+        public String toString() {
+            return count + " -> " + value;
+        }
+
+        public void inc() {
+            count++;
+        }
+
+        public void add(int n) {
+            count += n;
+        }
+
+        public int getCount() {
+            return count;
+        }
+
+        public Object getValue() {
+            return value;
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Thu Mar 20 13:50:21 2014 +0100
@@ -120,6 +120,9 @@
                                 errors.add(e.getMessage());
                             } catch (LinkageError e) {
                                 // suppress linkages errors resulting from eager resolution
+                            } catch (BailoutException e) {
+                                // Graal bail outs on certain patterns in Java bytecode (e.g.,
+                                // unbalanced monitors introduced by jacoco).
                             } catch (Throwable e) {
                                 StringWriter sw = new StringWriter();
                                 e.printStackTrace(new PrintWriter(sw));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -130,7 +130,7 @@
     @Before
     public void beforeTest() {
         assert debugScope == null;
-        debugScope = Debug.scope(getClass().getSimpleName());
+        debugScope = Debug.scope(getClass());
     }
 
     @After
@@ -498,7 +498,7 @@
     }
 
     private CompilationResult compileBaseline(ResolvedJavaMethod javaMethod) {
-        try (Scope bds = Debug.scope("compileBaseline", javaMethod, providers.getCodeCache())) {
+        try (Scope bds = Debug.scope("CompileBaseline", javaMethod, providers.getCodeCache())) {
             BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess());
             return baselineCompiler.generate(javaMethod, -1, getBackend(), new CompilationResult(), javaMethod, CompilationResultBuilderFactory.Default);
         } catch (Throwable e) {
@@ -629,7 +629,7 @@
         final int id = compilationId.incrementAndGet();
 
         InstalledCode installedCode = null;
-        try (Scope ds = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true))) {
+        try (AllocSpy spy = AllocSpy.open(method); Scope ds = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true))) {
             final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed();
             if (printCompilation) {
                 TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s ...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature()));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Thu Mar 20 13:50:21 2014 +0100
@@ -149,7 +149,7 @@
     protected void prepareGraph(String snippet, final boolean iterativeEscapeAnalysis) {
         ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(getMethod(snippet));
         graph = new StructuredGraph(method);
-        try (Scope s = Debug.scope(getClass().getSimpleName(), graph, method, getCodeCache())) {
+        try (Scope s = Debug.scope(getClass(), graph, method, getCodeCache())) {
             new GraphBuilderPhase.Instance(getMetaAccess(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
             Assumptions assumptions = new Assumptions(false);
             context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 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.test.ea;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.Debug.Scope;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+/**
+ * Tests {@link AbstractNewObjectNode#simplify(com.oracle.graal.graph.spi.SimplifierTool)}.
+ * 
+ */
+public class PoorMansEATest extends GraalCompilerTest {
+    public static class A {
+        public A obj;
+    }
+
+    public static A test1Snippet() {
+        A a = new A();
+        a.obj = a;
+        return null;
+    }
+
+    @Test
+    public void test1() {
+        test("test1Snippet");
+    }
+
+    private void test(final String snippet) {
+        try (Scope s = Debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) {
+            StructuredGraph graph = parse(snippet);
+            Assumptions assumptions = new Assumptions(false);
+            HighTierContext highTierContext = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+            new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext);
+            PhaseContext context = new PhaseContext(getProviders(), assumptions);
+            new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+
+            // remove framestates in order to trigger the simplification.
+            cleanup: for (FrameState fs : graph.getNodes(FrameState.class).snapshot()) {
+                for (Node input : fs.inputs()) {
+                    if (input instanceof NewInstanceNode) {
+                        fs.replaceAtUsages(null);
+                        fs.safeDelete();
+                        continue cleanup;
+                    }
+                }
+            }
+            new CanonicalizerPhase(true).apply(graph, context);
+        } catch (Throwable e) {
+            throw Debug.handle(e);
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Mar 20 13:50:21 2014 +0100
@@ -198,14 +198,9 @@
         suites.getLowTier().apply(graph, lowTierContext);
         graph.maybeCompress();
 
-        // we do not want to store statistics about OSR compilations because it may prevent inlining
-        if (!graph.isOSR()) {
-            InliningPhase.storeStatisticsAfterLowTier(graph);
-        }
-
         SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
-        Debug.dump(schedule, "final schedule");
+        Debug.dump(schedule, "Final HIR schedule");
         return schedule;
 
     }
@@ -298,18 +293,14 @@
 
         if (Debug.isMeterEnabled()) {
             List<DataPatch> ldp = compilationResult.getDataReferences();
-            DebugMetric[] dms = new DebugMetric[Kind.values().length];
+            Kind[] kindValues = Kind.values();
+            DebugMetric[] dms = new DebugMetric[kindValues.length];
             for (int i = 0; i < dms.length; i++) {
-                dms[i] = Debug.metric("DataPatches-" + Kind.values()[i].toString());
+                dms[i] = Debug.metric("DataPatches-%s", kindValues[i]);
             }
-            DebugMetric dmRaw = Debug.metric("DataPatches-raw");
 
             for (DataPatch dp : ldp) {
-                if (dp.getConstant() != null) {
-                    dms[dp.getConstant().getKind().ordinal()].add(1);
-                } else {
-                    dmRaw.add(1);
-                }
+                dms[dp.data.getKind().ordinal()].add(1);
             }
 
             Debug.metric("CompilationResults").increment();
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Thu Mar 20 13:50:21 2014 +0100
@@ -70,11 +70,8 @@
         super(allocator, unhandledFixedFirst, unhandledAnyFirst);
 
         // If all allocatable registers are caller saved, then no registers are live across a call
-        // site.
-        // The register allocator can save time not trying to find a register at a call site.
-        HashSet<Register> registers = new HashSet<>(Arrays.asList(allocator.frameMap.registerConfig.getAllocatableRegisters()));
-        registers.removeAll(Arrays.asList(allocator.frameMap.registerConfig.getCallerSaveRegisters()));
-        allocator.callKillsRegisters = registers.size() == 0;
+        // site. The register allocator can save time not trying to find a register at a call site.
+        allocator.callKillsRegisters = allocator.frameMap.registerConfig.areAllAllocatableRegistersCallerSaved();
 
         moveResolver = new MoveResolver(allocator);
         spillIntervals = Util.uncheckedCast(new List[allocator.registers.length]);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Thu Mar 20 13:50:21 2014 +0100
@@ -25,15 +25,12 @@
 import static com.oracle.graal.compiler.phases.HighTier.Options.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.phases.verify.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
 public class HighTier extends PhaseSuite<HighTierContext> {
@@ -41,8 +38,6 @@
     public static class Options {
 
         // @formatter:off
-        @Option(help = "")
-        public static final OptionValue<Boolean> VerifyUsageWithEquals = new OptionValue<>(true);
         @Option(help = "Enable inlining")
         public static final OptionValue<Boolean> Inline = new OptionValue<>(true);
         // @formatter:on
@@ -51,11 +46,6 @@
     public HighTier() {
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue());
 
-        if (VerifyUsageWithEquals.getValue()) {
-            appendPhase(new VerifyUsageWithEquals(Value.class));
-            appendPhase(new VerifyUsageWithEquals(Register.class));
-        }
-
         if (OptCanonicalizer.getValue()) {
             appendPhase(canonicalizer);
         }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Thu Mar 20 13:50:21 2014 +0100
@@ -23,6 +23,7 @@
 package com.oracle.graal.debug;
 
 import static com.oracle.graal.debug.Debug.Initialization.*;
+import static java.util.FormattableFlags.*;
 
 import java.io.*;
 import java.util.*;
@@ -129,7 +130,7 @@
 
     /**
      * Gets a string composed of the names in the current nesting of debug
-     * {@linkplain #scope(String, Object...) scopes} separated by {@code '.'}.
+     * {@linkplain #scope(Object) scopes} separated by {@code '.'}.
      */
     public static String currentScope() {
         if (ENABLED) {
@@ -140,7 +141,7 @@
     }
 
     /**
-     * Represents a debug scope entered by {@link Debug#scope(String, Object...)} or
+     * Represents a debug scope entered by {@link Debug#scope(Object)} or
      * {@link Debug#sandbox(String, DebugConfig, Object...)}. Leaving the scope is achieved via
      * {@link #close()}.
      */
@@ -162,14 +163,67 @@
      * }
      * </pre>
      * 
+     * The {@code name} argument is subject to the following type based conversion before having
+     * {@link Object#toString()} called on it:
+     * 
+     * <pre>
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * </pre>
+     * 
      * @param name the name of the new scope
-     * @param context objects to be appended to the {@linkplain #context() current} debug context
      * @return the scope entered by this method which will be exited when its {@link Scope#close()}
      *         method is called
      */
-    public static Scope scope(String name, Object... context) {
+    public static Scope scope(Object name) {
+        if (ENABLED) {
+            return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @see #scope(Object)
+     * @param context an object to be appended to the {@linkplain #context() current} debug context
+     */
+    public static Scope scope(Object name, Object context) {
         if (ENABLED) {
-            return DebugScope.getInstance().scope(name, null, context);
+            return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @see #scope(Object)
+     * @param context1 first object to be appended to the {@linkplain #context() current} debug
+     *            context
+     * @param context2 second object to be appended to the {@linkplain #context() current} debug
+     *            context
+     */
+    public static Scope scope(Object name, Object context1, Object context2) {
+        if (ENABLED) {
+            return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context1, context2);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @see #scope(Object)
+     * @param context1 first object to be appended to the {@linkplain #context() current} debug
+     *            context
+     * @param context2 second object to be appended to the {@linkplain #context() current} debug
+     *            context
+     * @param context3 third object to be appended to the {@linkplain #context() current} debug
+     *            context
+     */
+    public static Scope scope(Object name, Object context1, Object context2, Object context3) {
+        if (ENABLED) {
+            return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context1, context2, context3);
         } else {
             return null;
         }
@@ -195,7 +249,7 @@
      * @return the scope entered by this method which will be exited when its {@link Scope#close()}
      *         method is called
      */
-    public static Scope sandbox(String name, DebugConfig config, Object... context) {
+    public static Scope sandbox(CharSequence name, DebugConfig config, Object... context) {
         if (ENABLED) {
             DebugConfig sandboxConfig = config == null ? silentConfig() : config;
             return DebugScope.getInstance().scope(name, sandboxConfig, context);
@@ -221,10 +275,10 @@
     /**
      * Handles an exception in the context of the debug scope just exited. The just exited scope
      * must have the current scope as its parent which will be the case if the try-with-resource
-     * pattern recommended by {@link #scope(String, Object...)} and
+     * pattern recommended by {@link #scope(Object)} and
      * {@link #sandbox(String, DebugConfig, Object...)} is used
      * 
-     * @see #scope(String, Object...)
+     * @see #scope(Object)
      * @see #sandbox(String, DebugConfig, Object...)
      */
     public static RuntimeException handle(Throwable exception) {
@@ -242,20 +296,79 @@
     }
 
     /**
-     * Prints an indented message to the current debug scopes's logging stream if logging is enabled
-     * in the scope.
+     * Prints a message to the current debug scope's logging stream if logging is enabled.
+     * 
+     * @param msg the message to log
+     */
+    public static void log(String msg) {
+        if (ENABLED) {
+            DebugScope.getInstance().log(msg);
+        }
+    }
+
+    /**
+     * Prints a message to the current debug scope's logging stream if logging is enabled.
      * 
-     * @param msg The format string of the log message
-     * @param args The arguments referenced by the log message string
-     * @see Indent#log
+     * @param format a format string
+     * @param arg the argument referenced by the format specifiers in {@code format}
+     */
+    public static void log(String format, Object arg) {
+        if (ENABLED) {
+            DebugScope.getInstance().log(format, arg);
+        }
+    }
+
+    /**
+     * @see #log(String, Object)
+     */
+    public static void log(String format, Object arg1, Object arg2) {
+        if (ENABLED) {
+            DebugScope.getInstance().log(format, arg1, arg2);
+        }
+    }
+
+    /**
+     * @see #log(String, Object)
      */
-    public static void log(String msg, Object... args) {
+    public static void log(String format, Object arg1, Object arg2, Object arg3) {
+        if (ENABLED) {
+            DebugScope.getInstance().log(format, arg1, arg2, arg3);
+        }
+    }
+
+    /**
+     * @see #log(String, Object)
+     */
+    public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) {
         if (ENABLED) {
-            DebugScope.getInstance().log(msg, args);
+            DebugScope.getInstance().log(format, arg1, arg2, arg3, arg4);
+        }
+    }
+
+    /**
+     * @see #log(String, Object)
+     */
+    public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
+        if (ENABLED) {
+            DebugScope.getInstance().log(format, arg1, arg2, arg3, arg4, arg5);
         }
     }
 
     /**
+     * Prints a message to the current debug scope's logging stream. This method must only be called
+     * if debugging is {@linkplain Debug#isEnabled() enabled}.
+     * 
+     * @param format a format string
+     * @param args the arguments referenced by the format specifiers in {@code format}
+     */
+    public static void logv(String format, Object... args) {
+        if (!ENABLED) {
+            throw new InternalError("Use of Debug.logv() must be guarded by a test of Debug.isEnabled()");
+        }
+        DebugScope.getInstance().log(format, args);
+    }
+
+    /**
      * The same as {@link #log}, but without line termination and without indentation.
      */
     public static void printf(String msg, Object... args) {
@@ -379,14 +492,87 @@
      * <p>
      * A disabled metric has virtually no overhead.
      */
-    public static DebugMetric metric(String name) {
-        if (Boolean.getBoolean(ENABLE_METRIC_PROPERTY_NAME_PREFIX + name)) {
-            return new MetricImpl(name, false);
-        } else if (ENABLED) {
-            return new MetricImpl(name, true);
-        } else {
+    public static DebugMetric metric(CharSequence name) {
+        if (enabledMetrics == null && !ENABLED) {
             return VOID_METRIC;
         }
+        return createMetric("%s", name, null);
+    }
+
+    public static String applyFormattingFlagsAndWidth(String s, int flags, int width) {
+        if (flags == 0 && width < 0) {
+            return s;
+        }
+        StringBuilder sb = new StringBuilder(s);
+
+        // apply width and justification
+        int len = sb.length();
+        if (len < width) {
+            for (int i = 0; i < width - len; i++) {
+                if ((flags & LEFT_JUSTIFY) == LEFT_JUSTIFY) {
+                    sb.append(' ');
+                } else {
+                    sb.insert(0, ' ');
+                }
+            }
+        }
+
+        String res = sb.toString();
+        if ((flags & UPPERCASE) == UPPERCASE) {
+            res = res.toUpperCase();
+        }
+        return res;
+    }
+
+    /**
+     * Creates a debug metric. Invoking this method is equivalent to:
+     * 
+     * <pre>
+     * Debug.metric(format, arg, null)
+     * </pre>
+     * 
+     * except that the string formatting only happens if metering is enabled.
+     * 
+     * @see #metric(String, Object, Object)
+     */
+    public static DebugMetric metric(String format, Object arg) {
+        if (enabledMetrics == null && !ENABLED) {
+            return VOID_METRIC;
+        }
+        return createMetric(format, arg, null);
+    }
+
+    /**
+     * Creates a debug metric. Invoking this method is equivalent to:
+     * 
+     * <pre>
+     * Debug.metric(String.format(format, arg1, arg2))
+     * </pre>
+     * 
+     * except that the string formatting only happens if metering is enabled. In addition, each
+     * argument is subject to the following type based conversion before being passed as an argument
+     * to {@link String#format(String, Object...)}:
+     * 
+     * <pre>
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * </pre>
+     * 
+     * @see #metric(CharSequence)
+     */
+    public static DebugMetric metric(String format, Object arg1, Object arg2) {
+        if (enabledMetrics == null && !ENABLED) {
+            return VOID_METRIC;
+        }
+        return createMetric(format, arg1, arg2);
+    }
+
+    private static DebugMetric createMetric(String format, Object arg1, Object arg2) {
+        String name = formatDebugName(format, arg1, arg2);
+        boolean conditional = enabledMetrics != null && enabledMetrics.contains(name);
+        return new MetricImpl(name, conditional);
     }
 
     /**
@@ -495,15 +681,33 @@
     };
 
     /**
-     * @see #timer(String)
+     * @see #timer(CharSequence)
      */
     public static final String ENABLE_TIMER_PROPERTY_NAME_PREFIX = "graal.debug.timer.";
 
     /**
-     * @see #metric(String)
+     * @see #metric(CharSequence)
      */
     public static final String ENABLE_METRIC_PROPERTY_NAME_PREFIX = "graal.debug.metric.";
 
+    private static final Set<String> enabledMetrics;
+    private static final Set<String> enabledTimers;
+    static {
+        Set<String> metrics = new HashSet<>();
+        Set<String> timers = new HashSet<>();
+        for (Map.Entry<Object, Object> e : System.getProperties().entrySet()) {
+            String name = e.getKey().toString();
+            if (name.startsWith(ENABLE_METRIC_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) {
+                metrics.add(name.substring(ENABLE_METRIC_PROPERTY_NAME_PREFIX.length()));
+            }
+            if (name.startsWith(ENABLE_TIMER_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) {
+                timers.add(name.substring(ENABLE_TIMER_PROPERTY_NAME_PREFIX.length()));
+            }
+        }
+        enabledMetrics = metrics.isEmpty() ? null : metrics;
+        enabledTimers = timers.isEmpty() ? null : timers;
+    }
+
     /**
      * Creates a {@linkplain DebugTimer timer} that is enabled iff debugging is
      * {@linkplain #isEnabled() enabled} or the system property whose name is formed by adding to
@@ -514,14 +718,73 @@
      * <p>
      * A disabled timer has virtually no overhead.
      */
-    public static DebugTimer timer(String name) {
-        if (Boolean.getBoolean(ENABLE_TIMER_PROPERTY_NAME_PREFIX + name)) {
-            return new TimerImpl(name, false);
-        } else if (ENABLED) {
-            return new TimerImpl(name, true);
-        } else {
+    public static DebugTimer timer(CharSequence name) {
+        if (enabledTimers == null && !ENABLED) {
+            return VOID_TIMER;
+        }
+        return createTimer("%s", name, null);
+    }
+
+    /**
+     * Creates a debug timer. Invoking this method is equivalent to:
+     * 
+     * <pre>
+     * Debug.timer(format, arg, null)
+     * </pre>
+     * 
+     * except that the string formatting only happens if timing is enabled.
+     * 
+     * @see #timer(String, Object, Object)
+     */
+    public static DebugTimer timer(String format, Object arg) {
+        if (enabledTimers == null && !ENABLED) {
             return VOID_TIMER;
         }
+        return createTimer(format, arg, null);
+    }
+
+    /**
+     * Creates a debug timer. Invoking this method is equivalent to:
+     * 
+     * <pre>
+     * Debug.timer(String.format(format, arg1, arg2))
+     * </pre>
+     * 
+     * except that the string formatting only happens if timing is enabled. In addition, each
+     * argument is subject to the following type based conversion before being passed as an argument
+     * to {@link String#format(String, Object...)}:
+     * 
+     * <pre>
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * </pre>
+     * 
+     * @see #timer(CharSequence)
+     */
+    public static DebugTimer timer(String format, Object arg1, Object arg2) {
+        if (enabledTimers == null && !ENABLED) {
+            return VOID_TIMER;
+        }
+        return createTimer(format, arg1, arg2);
+    }
+
+    public static Object convertFormatArg(Object arg) {
+        if (arg instanceof Class) {
+            return ((Class) arg).getSimpleName();
+        }
+        return arg;
+    }
+
+    private static String formatDebugName(String format, Object arg1, Object arg2) {
+        return String.format(format, convertFormatArg(arg1), convertFormatArg(arg2));
+    }
+
+    private static DebugTimer createTimer(String format, Object arg1, Object arg2) {
+        String name = formatDebugName(format, arg1, arg2);
+        boolean conditional = enabledTimers != null && enabledTimers.contains(name);
+        return new TimerImpl(name, conditional);
     }
 
     private static final DebugTimer VOID_TIMER = new DebugTimer() {
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java	Thu Mar 20 13:50:21 2014 +0100
@@ -28,10 +28,7 @@
 public interface DebugConfig {
 
     /**
-     * Determines if logging is enabled in the {@linkplain Debug#currentScope() current debug scope}
-     * .
-     * 
-     * @see Debug#log(String, Object...)
+     * Determines if logging is on in the {@linkplain Debug#currentScope() current debug scope} .
      */
     boolean isLogEnabled();
 
@@ -45,7 +42,7 @@
      * Determines if metering is enabled in the {@linkplain Debug#currentScope() current debug
      * scope}.
      * 
-     * @see Debug#metric(String)
+     * @see Debug#metric(CharSequence)
      */
     boolean isMeterEnabled();
 
@@ -76,7 +73,7 @@
     void removeFromContext(Object o);
 
     /**
-     * @see Debug#timer(String)
+     * @see Debug#timer(CharSequence)
      */
     boolean isTimeEnabled();
 
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java	Thu Mar 20 13:50:21 2014 +0100
@@ -72,6 +72,10 @@
             count++;
         }
 
+        public void add(int n) {
+            count += n;
+        }
+
         public int getCount() {
             return count;
         }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Thu Mar 20 13:50:21 2014 +0100
@@ -231,13 +231,13 @@
      * @param newContextObjects objects to be appended to the debug context
      * @return the new scope which will be exited when its {@link #close()} method is called
      */
-    public DebugScope scope(String name, DebugConfig sandboxConfig, Object... newContextObjects) {
+    public DebugScope scope(CharSequence name, DebugConfig sandboxConfig, Object... newContextObjects) {
         DebugScope newScope = null;
         if (sandboxConfig != null) {
-            newScope = new DebugScope(name, name, this, true, newContextObjects);
+            newScope = new DebugScope(name.toString(), name.toString(), this, true, newContextObjects);
             configTL.set(sandboxConfig);
         } else {
-            newScope = this.createChild(name, newContextObjects);
+            newScope = this.createChild(name.toString(), newContextObjects);
         }
         instanceTL.set(newScope);
         newScope.updateFlags();
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Thu Mar 20 13:50:21 2014 +0100
@@ -458,6 +458,7 @@
      * newInput: removes this node from oldInput's usages and adds this node to newInput's usages.
      */
     protected void updateUsages(Node oldInput, Node newInput) {
+        assert isAlive() && (newInput == null || newInput.isAlive()) : "adding " + newInput + " to " + this + " instead of " + oldInput;
         if (oldInput != newInput) {
             if (oldInput != null) {
                 if (oldInput.recordsUsages()) {
@@ -482,6 +483,7 @@
      * this node to newSuccessor's predecessors.
      */
     protected void updatePredecessor(Node oldSuccessor, Node newSuccessor) {
+        assert isAlive() && (newSuccessor == null || newSuccessor.isAlive()) : "adding " + newSuccessor + " to " + this + " instead of " + oldSuccessor;
         assert graph == null || !graph.isFrozen();
         if (oldSuccessor != newSuccessor) {
             if (oldSuccessor != null) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Thu Mar 20 13:50:21 2014 +0100
@@ -234,7 +234,7 @@
         }
 
         isLeafNode = (this.inputOffsets.length == 0 && this.successorOffsets.length == 0);
-        nodeIterableCount = Debug.metric("NodeIterable_" + shortName);
+        nodeIterableCount = Debug.metric("NodeIterable_%s", shortName);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu Mar 20 13:50:21 2014 +0100
@@ -41,8 +41,8 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.hotspot.nfi.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
@@ -254,7 +254,7 @@
     public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedEntry) {
         HotSpotProviders providers = getProviders();
         if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) {
-            crb.recordMark(Marks.MARK_UNVERIFIED_ENTRY);
+            MarkId.recordMark(crb, MarkId.UNVERIFIED_ENTRY);
             CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[]{providers.getMetaAccess().lookupJavaType(Object.class)}, getTarget(), false);
             Register inlineCacheKlass = rax; // see definition of IC_Klass in
                                              // c1_LIRAssembler_x86.cpp
@@ -276,9 +276,9 @@
         }
 
         asm.align(config.codeEntryAlignment);
-        crb.recordMark(Marks.MARK_OSR_ENTRY);
+        MarkId.recordMark(crb, MarkId.OSR_ENTRY);
         asm.bind(verifiedEntry);
-        crb.recordMark(Marks.MARK_VERIFIED_ENTRY);
+        MarkId.recordMark(crb, MarkId.VERIFIED_ENTRY);
     }
 
     /**
@@ -298,9 +298,9 @@
         HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext;
         if (!frameContext.isStub) {
             HotSpotForeignCallsProvider foreignCalls = providers.getForeignCalls();
-            crb.recordMark(Marks.MARK_EXCEPTION_HANDLER_ENTRY);
+            MarkId.recordMark(crb, MarkId.EXCEPTION_HANDLER_ENTRY);
             AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, false, null);
-            crb.recordMark(Marks.MARK_DEOPT_HANDLER_ENTRY);
+            MarkId.recordMark(crb, MarkId.DEOPT_HANDLER_ENTRY);
             AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_HANDLER), null, false, null);
         } else {
             // No need to emit the stubs for entries back into the method since
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Thu Mar 20 13:50:21 2014 +0100
@@ -89,7 +89,7 @@
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
         final boolean inlineObjects = true;
-        return new TargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+        return new HotSpotTargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Mar 20 13:50:21 2014 +0100
@@ -488,8 +488,6 @@
     protected static Constant compress(Constant c, CompressEncoding encoding) {
         if (c.getKind() == Kind.Long) {
             return Constant.forIntegerKind(Kind.Int, (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL), c.getPrimitiveAnnotation());
-        } else if (c.getKind() == Kind.Object) {
-            return Constant.forNarrowOop(c.asObject());
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -538,8 +536,7 @@
             if (canStoreConstant(c, isCompressed)) {
                 if (isCompressed) {
                     if (c.getKind() == Kind.Object) {
-                        Constant value = c.isNull() ? c : compress(c, config.getOopEncoding());
-                        append(new StoreCompressedConstantOp(kind, storeAddress, value, state));
+                        append(new StoreCompressedConstantOp(kind, storeAddress, c, state));
                     } else if (c.getKind() == Kind.Long) {
                         // It's always a good idea to directly store compressed constants since they
                         // have to be materialized as 64 bits encoded otherwise.
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Thu Mar 20 13:50:21 2014 +0100
@@ -33,6 +33,7 @@
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
+import com.oracle.graal.hotspot.data.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
@@ -51,6 +52,9 @@
         public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
             if (kind == Kind.Long) {
                 if (NumUtil.isInt(input.asLong())) {
+                    if (input.getPrimitiveAnnotation() != null) {
+                        crb.recordInlineDataInCode(new MetaspaceData(0, input.asLong(), input.getPrimitiveAnnotation(), true));
+                    }
                     masm.movl(address.toAddress(), (int) input.asLong());
                 } else {
                     throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
@@ -59,7 +63,7 @@
                 if (input.isNull()) {
                     masm.movl(address.toAddress(), 0);
                 } else if (crb.target.inlineObjects) {
-                    crb.recordInlineDataInCode(input);
+                    crb.recordInlineDataInCode(new OopData(0, input.asObject(), true));
                     masm.movl(address.toAddress(), 0xDEADDEAD);
                 } else {
                     throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Thu Mar 20 13:50:21 2014 +0100
@@ -33,6 +33,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.nodes.type.*;
 
 public class AMD64HotSpotRegisterConfig implements RegisterConfig {
 
@@ -47,6 +48,8 @@
      */
     private final Register[] callerSaved;
 
+    private final boolean allAllocatableAreCallerSaved;
+
     private final HashMap<PlatformKind, Register[]> categorized = new HashMap<>();
 
     private final RegisterAttributes[] attributesMap;
@@ -61,9 +64,16 @@
             return categorized.get(kind);
         }
 
+        PlatformKind primitiveKind;
+        if (kind == NarrowOopStamp.NarrowOop) {
+            primitiveKind = Kind.Int;
+        } else {
+            primitiveKind = kind;
+        }
+
         ArrayList<Register> list = new ArrayList<>();
         for (Register reg : getAllocatableRegisters()) {
-            if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) {
+            if (architecture.canStoreValue(reg.getRegisterCategory(), primitiveKind)) {
                 list.add(reg);
             }
         }
@@ -144,6 +154,7 @@
         callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
         assert callerSaved.length == allocatable.length || RegisterPressure.getValue() != null;
 
+        allAllocatableAreCallerSaved = true;
         attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters);
     }
 
@@ -153,6 +164,11 @@
     }
 
     @Override
+    public boolean areAllAllocatableRegistersCallerSaved() {
+        return allAllocatableAreCallerSaved;
+    }
+
+    @Override
     public Register getRegisterForRole(int index) {
         throw new UnsupportedOperationException();
     }
@@ -211,7 +227,7 @@
 
             if (locations[i] == null) {
                 locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out);
-                currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize);
+                currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize);
             }
         }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java	Thu Mar 20 13:50:21 2014 +0100
@@ -24,13 +24,13 @@
 
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.asm.NumUtil.*;
-import static com.oracle.graal.hotspot.bridge.Marks.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
@@ -82,21 +82,21 @@
             // co-located with the immutable code.
             asm.movq(scratch, (AMD64Address) crb.recordDataReferenceInCode(pollingPageAddress, alignment));
             final int pos = asm.position();
-            crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR);
+            MarkId.recordMark(crb, atReturn ? MarkId.POLL_RETURN_FAR : MarkId.POLL_FAR);
             if (state != null) {
                 crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
             }
             asm.testl(rax, new AMD64Address(scratch));
         } else if (isPollingPageFar(config)) {
             asm.movq(scratch, config.safepointPollingAddress);
-            crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR);
+            MarkId.recordMark(crb, atReturn ? MarkId.POLL_RETURN_FAR : MarkId.POLL_FAR);
             final int pos = asm.position();
             if (state != null) {
                 crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
             }
             asm.testl(rax, new AMD64Address(scratch));
         } else {
-            crb.recordMark(atReturn ? MARK_POLL_RETURN_NEAR : MARK_POLL_NEAR);
+            MarkId.recordMark(crb, atReturn ? MarkId.POLL_RETURN_NEAR : MarkId.POLL_NEAR);
             final int pos = asm.position();
             if (state != null) {
                 crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java	Thu Mar 20 13:50:21 2014 +0100
@@ -26,7 +26,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
@@ -55,7 +55,7 @@
         // The mark for an invocation that uses an inline cache must be placed at the
         // instruction that loads the Klass from the inline cache.
         AMD64Move.move(crb, masm, AMD64.rbx.asValue(Kind.Long), metaspaceMethod);
-        crb.recordMark(invokeKind == InvokeKind.Static ? Marks.MARK_INVOKESTATIC : Marks.MARK_INVOKESPECIAL);
+        MarkId.recordMark(crb, invokeKind == InvokeKind.Static ? MarkId.INVOKESTATIC : MarkId.INVOKESPECIAL);
         // This must be emitted exactly like this to ensure it's patchable
         masm.movq(AMD64.rax, HotSpotGraalRuntime.runtime().getConfig().nonOopBits);
         super.emitCode(crb, masm);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java	Thu Mar 20 13:50:21 2014 +0100
@@ -28,7 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
 import com.oracle.graal.lir.asm.*;
@@ -53,7 +53,7 @@
     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
         // The mark for an invocation that uses an inline cache must be placed at the
         // instruction that loads the Klass from the inline cache.
-        crb.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE);
+        MarkId.recordMark(crb, invokeKind == Virtual ? MarkId.INVOKEVIRTUAL : MarkId.INVOKEINTERFACE);
         // This must be emitted exactly like this to ensure it's patchable
         masm.movq(AMD64.rax, HotSpotGraalRuntime.runtime().getConfig().nonOopBits);
         super.emitCode(crb, masm);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Thu Mar 20 13:50:21 2014 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp;
@@ -58,7 +58,7 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-        crb.recordMark(Marks.MARK_INLINE_INVOKE);
+        MarkId.recordMark(crb, MarkId.INLINE_INVOKE);
         Register callReg = asRegister(targetAddress);
         assert !callReg.equals(METHOD);
         AMD64Call.indirectCall(crb, masm, callReg, callTarget, state);
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java	Thu Mar 20 13:50:21 2014 +0100
@@ -62,7 +62,7 @@
         final int stackFrameAlignment = 8;
         final int implicitNullCheckLimit = 0;
         final boolean inlineObjects = true;
-        return new TargetDescription(new HSAIL(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+        return new HotSpotTargetDescription(new HSAIL(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int);
     }
 
     public String getArchitecture() {
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Thu Mar 20 13:50:21 2014 +0100
@@ -165,7 +165,7 @@
             if (canStoreConstant(c, isCompressed)) {
                 if (isCompressed) {
                     if ((c.getKind() == Kind.Object) && c.isNull()) {
-                        append(new StoreConstantOp(Kind.NarrowOop, storeAddress, c, state));
+                        append(new StoreConstantOp(Kind.Int, storeAddress, Constant.forInt(0), state));
                     } else {
                         throw GraalInternalError.shouldNotReachHere("can't handle: " + access);
                     }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java	Thu Mar 20 13:50:21 2014 +0100
@@ -59,7 +59,7 @@
         final int stackFrameAlignment = 1;
         final int implicitNullCheckLimit = 0;
         final boolean inlineObjects = true;
-        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+        return new HotSpotTargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int);
     }
 
     public String getArchitecture() {
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java	Thu Mar 20 13:50:21 2014 +0100
@@ -74,6 +74,11 @@
     }
 
     @Override
+    public boolean areAllAllocatableRegistersCallerSaved() {
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
     public Register getRegisterForRole(int index) {
         throw GraalInternalError.unimplemented("PTXHotSpotRegisterConfig.getRegisterForRole()");
     }
@@ -133,7 +138,7 @@
 
             if (locations[i] == null) {
                 locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out);
-                currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize);
+                currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize);
             }
         }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Mar 20 13:50:21 2014 +0100
@@ -48,8 +48,8 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
@@ -201,7 +201,7 @@
         // Emit the prefix
 
         if (unverifiedStub != null) {
-            crb.recordMark(Marks.MARK_UNVERIFIED_ENTRY);
+            MarkId.recordMark(crb, MarkId.UNVERIFIED_ENTRY);
             // We need to use JavaCall here because we haven't entered the frame yet.
             CallingConvention cc = regConfig.getCallingConvention(JavaCall, null, new JavaType[]{getProviders().getMetaAccess().lookupJavaType(Object.class)}, getTarget(), false);
             Register inlineCacheKlass = g5; // see MacroAssembler::ic_call
@@ -216,8 +216,8 @@
         }
 
         masm.align(config.codeEntryAlignment);
-        crb.recordMark(Marks.MARK_OSR_ENTRY);
-        crb.recordMark(Marks.MARK_VERIFIED_ENTRY);
+        MarkId.recordMark(crb, MarkId.OSR_ENTRY);
+        MarkId.recordMark(crb, MarkId.VERIFIED_ENTRY);
 
         // Emit code for the LIR
         crb.emit(lir);
@@ -225,9 +225,9 @@
         HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext;
         HotSpotForeignCallsProvider foreignCalls = getProviders().getForeignCalls();
         if (!frameContext.isStub) {
-            crb.recordMark(Marks.MARK_EXCEPTION_HANDLER_ENTRY);
+            MarkId.recordMark(crb, MarkId.EXCEPTION_HANDLER_ENTRY);
             SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, false, null);
-            crb.recordMark(Marks.MARK_DEOPT_HANDLER_ENTRY);
+            MarkId.recordMark(crb, MarkId.DEOPT_HANDLER_ENTRY);
             SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(DEOPT_HANDLER), null, false, null);
         } else {
             // No need to emit the stubs for entries back into the method since
@@ -245,5 +245,4 @@
     public NativeFunctionInterface getNativeFunctionInterface() {
         throw GraalInternalError.unimplemented("No NativeFunctionInterface of SPARC");
     }
-
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Thu Mar 20 13:50:21 2014 +0100
@@ -42,7 +42,7 @@
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
         final boolean inlineObjects = true;
-        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+        return new HotSpotTargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int);
     }
 
     public HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend host) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCodeCacheProvider.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCodeCacheProvider.java	Thu Mar 20 13:50:21 2014 +0100
@@ -34,6 +34,6 @@
 
     @Override
     protected RegisterConfig createRegisterConfig() {
-        return new SPARCHotSpotRegisterConfig(getTarget().arch, runtime.getConfig());
+        return new SPARCHotSpotRegisterConfig(getTarget(), runtime.getConfig());
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Thu Mar 20 13:50:21 2014 +0100
@@ -130,10 +130,10 @@
         return registers;
     }
 
-    public SPARCHotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) {
-        this.architecture = architecture;
+    public SPARCHotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) {
+        this.architecture = target.arch;
 
-        csl = new CalleeSaveLayout(architecture, -1, -1, architecture.getWordSize(), calleeSaveRegisters);
+        csl = new CalleeSaveLayout(target, -1, -1, target.arch.getWordSize(), calleeSaveRegisters);
         allocatable = initAllocatable(config.useCompressedOops);
         attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
     }
@@ -144,6 +144,11 @@
     }
 
     @Override
+    public boolean areAllAllocatableRegistersCallerSaved() {
+        return false;
+    }
+
+    @Override
     public Register getRegisterForRole(int index) {
         throw new UnsupportedOperationException();
     }
@@ -203,7 +208,7 @@
 
             if (locations[i] == null) {
                 locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out);
-                currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize);
+                currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize);
             }
         }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Thu Mar 20 13:50:21 2014 +0100
@@ -23,13 +23,13 @@
 package com.oracle.graal.hotspot.sparc;
 
 import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
-import static com.oracle.graal.hotspot.bridge.Marks.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.asm.*;
@@ -61,7 +61,7 @@
     public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) {
         final int pos = masm.position();
         new Setx(config.safepointPollingAddress, scratch).emit(masm);
-        crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR);
+        MarkId.recordMark(crb, atReturn ? MarkId.POLL_RETURN_FAR : MarkId.POLL_FAR);
         if (state != null) {
             crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
         }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Thu Mar 20 13:50:21 2014 +0100
@@ -28,7 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.SPARCCall.DirectCallOp;
@@ -42,7 +42,6 @@
 @Opcode("CALL_DIRECT")
 final class SPARCHotspotDirectStaticCallOp extends DirectCallOp {
 
-    private static final long nonOopBits = HotSpotGraalRuntime.runtime().getConfig().nonOopBits;
     private final Constant metaspaceMethod;
     private final InvokeKind invokeKind;
 
@@ -58,9 +57,9 @@
         // The mark for an invocation that uses an inline cache must be placed at the
         // instruction that loads the Klass from the inline cache.
         SPARCMove.move(crb, masm, g5.asValue(Kind.Long), metaspaceMethod);
-        crb.recordMark(invokeKind == InvokeKind.Static ? Marks.MARK_INVOKESTATIC : Marks.MARK_INVOKESPECIAL);
+        MarkId.recordMark(crb, invokeKind == InvokeKind.Static ? MarkId.INVOKESTATIC : MarkId.INVOKESPECIAL);
         // SPARCMove.move(crb, masm, g3.asValue(Kind.Long), Constant.LONG_0);
-        new Setx(nonOopBits, g3, true).emit(masm);
+        new Setx(HotSpotGraalRuntime.runtime().getConfig().nonOopBits, g3, true).emit(masm);
         super.emitCode(crb, masm);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java	Thu Mar 20 13:50:21 2014 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.sparc.SPARCCall.DirectCallOp;
 import com.oracle.graal.lir.asm.*;
@@ -54,7 +54,7 @@
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
         // The mark for an invocation that uses an inline cache must be placed at the
         // instruction that loads the Klass from the inline cache.
-        crb.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE);
+        MarkId.recordMark(crb, invokeKind == Virtual ? MarkId.INVOKEVIRTUAL : MarkId.INVOKEINTERFACE);
         new Setx(HotSpotGraalRuntime.runtime().getConfig().nonOopBits, g3, true).emit(masm);
         super.emitCode(crb, masm);
     }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java	Thu Mar 20 13:50:21 2014 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.sparc.SPARCCall.IndirectCallOp;
@@ -58,7 +58,7 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-        crb.recordMark(Marks.MARK_INLINE_INVOKE);
+        MarkId.recordMark(crb, MarkId.INLINE_INVOKE);
         Register callReg = asRegister(targetAddress);
         assert !callReg.equals(METHOD);
         SPARCCall.indirectCall(crb, masm, callReg, callTarget, state);
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -49,7 +49,7 @@
     protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) {
         HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
         HotSpotNmethod installedCode = new HotSpotNmethod(hsMethod, compResult.getName(), true);
-        HotSpotCompiledNmethod compiledNmethod = new HotSpotCompiledNmethod(runtime().getTarget().arch, hsMethod, compResult);
+        HotSpotCompiledNmethod compiledNmethod = new HotSpotCompiledNmethod(runtime().getTarget(), hsMethod, compResult);
         CodeInstallResult result = runtime().getCompilerToVM().installCode(compiledNmethod, installedCode, null);
         Assert.assertEquals("Error installing method " + method + ": " + result, result, CodeInstallResult.OK);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java	Thu Mar 20 13:50:21 2014 +0100
@@ -102,10 +102,10 @@
         }
     }
 
-    public void finish(HotSpotResolvedJavaMethod method) {
+    public void finish(HotSpotResolvedJavaMethod method, HotSpotInstalledCode code) {
         if (ENABLED) {
             duration = System.nanoTime() - startTime;
-            codeSize = method.getCompiledCodeSize();
+            codeSize = (int) code.getCodeSize();
             memoryUsed = getThreadAllocatedBytes() - threadAllocatedBytesStart;
             if (current.get().getLast() != this) {
                 throw new RuntimeException("mismatch in finish()");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Mar 20 13:50:21 2014 +0100
@@ -54,6 +54,8 @@
 
 public class CompilationTask implements Runnable, Comparable {
 
+    private static final long TIMESTAMP_START = System.currentTimeMillis();
+
     // Keep static finals in a group with withinEnqueue as the last one. CompilationTask can be
     // called from within it's own clinit so it needs to be careful about accessing state. Once
     // withinEnqueue is non-null we assume that CompilationTask is fully initialized.
@@ -279,8 +281,12 @@
 
             try (TimerCloseable b = CodeInstallationTime.start()) {
                 installedCode = installMethod(result);
+                if (!isOSR) {
+                    ProfilingInfo profile = method.getProfilingInfo();
+                    profile.setCompilerIRSize(StructuredGraph.class, graph.getNodeCount());
+                }
             }
-            stats.finish(method);
+            stats.finish(method, installedCode);
         } catch (BailoutException bailout) {
             BAILOUTS.increment();
             if (ExitVMOnBailout.getValue()) {
@@ -326,7 +332,24 @@
     private void printCompilation() {
         final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI;
         final int mod = method.getModifiers();
-        TTY.println(String.format("%7d %4d %c%c%c%c%c       %s %s(%d bytes)", 0, id, isOSR ? '%' : ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' ',
+        String compilerName = "";
+        if (HotSpotCIPrintCompilerName.getValue()) {
+            compilerName = "Graal:";
+        }
+        HotSpotVMConfig config = backend.getRuntime().getConfig();
+        int compLevel = config.compilationLevelFullOptimization;
+        char compLevelChar;
+        if (config.tieredCompilation) {
+            compLevelChar = '-';
+            if (compLevel != -1) {
+                compLevelChar = (char) ('0' + compLevel);
+            }
+        } else {
+            compLevelChar = ' ';
+        }
+        boolean hasExceptionHandlers = method.getExceptionHandlers().length > 0;
+        TTY.println(String.format("%s%7d %4d %c%c%c%c%c%c      %s %s(%d bytes)", compilerName, (System.currentTimeMillis() - TIMESTAMP_START), id, isOSR ? '%' : ' ',
+                        Modifier.isSynchronized(mod) ? 's' : ' ', hasExceptionHandlers ? '!' : ' ', blocking ? 'b' : ' ', Modifier.isNative(mod) ? 'n' : ' ', compLevelChar,
                         MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize()));
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Thu Mar 20 13:50:21 2014 +0100
@@ -27,7 +27,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
@@ -51,7 +50,8 @@
 
     /**
      * Descriptor for {@link ExceptionHandlerStub}. This stub is called by the
-     * {@linkplain Marks#MARK_EXCEPTION_HANDLER_ENTRY exception handler} in a compiled method.
+     * {@linkplain HotSpotVMConfig#codeInstallerMarkIdExceptionHandlerEntry exception handler} in a
+     * compiled method.
      */
     public static final ForeignCallDescriptor EXCEPTION_HANDLER = new ForeignCallDescriptor("exceptionHandler", void.class, Object.class, Word.class);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -22,21 +22,17 @@
  */
 package com.oracle.graal.hotspot;
 
-import java.nio.*;
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CompilationResult.CodeAnnotation;
 import com.oracle.graal.api.code.CompilationResult.CodeComment;
-import com.oracle.graal.api.code.CompilationResult.Data;
-import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.code.CompilationResult.ExceptionHandler;
 import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.api.code.CompilationResult.JumpTable;
 import com.oracle.graal.api.code.CompilationResult.Mark;
 import com.oracle.graal.api.code.CompilationResult.Site;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
+import com.oracle.graal.hotspot.data.*;
 
 /**
  * A {@link CompilationResult} with additional HotSpot-specific information required for installing
@@ -53,111 +49,6 @@
 
     public final DataSection dataSection;
 
-    /**
-     * Represents a reference to the data section. Before the code is installed, all {@link Data}
-     * items referenced by a {@link DataPatch} are put into the data section of the method, and
-     * replaced by {@link HotSpotData}.
-     */
-    public static final class HotSpotData extends Data {
-
-        /**
-         * The offset of the data item in the data section.
-         */
-        public int offset;
-
-        /**
-         * If the data item is an oop that needs to be patched by the runtime, this field contains
-         * the reference to the object.
-         */
-        public Constant constant;
-
-        public HotSpotData(int offset) {
-            super(0);
-            this.offset = offset;
-        }
-
-        @Override
-        public int getSize(Architecture arch) {
-            return 0;
-        }
-
-        @Override
-        public void emit(Architecture arch, ByteBuffer buffer) {
-        }
-    }
-
-    /**
-     * Represents the data section of a method.
-     */
-    public static final class DataSection {
-
-        /**
-         * The minimum alignment required for this data section.
-         */
-        public final int sectionAlignment;
-
-        /**
-         * The raw data contained in the data section.
-         */
-        public final byte[] data;
-
-        /**
-         * A list of locations where oop pointers need to be patched by the runtime.
-         */
-        public final HotSpotData[] patches;
-
-        public DataSection(Architecture arch, Site[] sites) {
-            int size = 0;
-            int patchCount = 0;
-            List<DataPatch> externalDataList = new ArrayList<>();
-
-            // find all external data items and determine total size of data section
-            for (Site site : sites) {
-                if (site instanceof DataPatch) {
-                    DataPatch dataPatch = (DataPatch) site;
-                    if (dataPatch.externalData != null) {
-                        Data d = dataPatch.externalData;
-                        size = NumUtil.roundUp(size, d.getAlignment());
-                        size += d.getSize(arch);
-                        externalDataList.add(dataPatch);
-                        if (dataPatch.getConstant() != null && dataPatch.getConstant().getKind() == Kind.Object) {
-                            patchCount++;
-                        }
-                    }
-                }
-            }
-
-            data = new byte[size];
-            patches = new HotSpotData[patchCount];
-            ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());
-            int index = 0;
-            int patchIndex = 0;
-            int alignment = 0;
-
-            // build data section
-            for (DataPatch dataPatch : externalDataList) {
-                Data d = dataPatch.externalData;
-
-                alignment = Math.max(alignment, d.getAlignment());
-                index = NumUtil.roundUp(index, d.getAlignment());
-                buffer.position(index);
-
-                HotSpotData hsData = new HotSpotData(index);
-                if (dataPatch.getConstant() != null && dataPatch.getConstant().getKind() == Kind.Object) {
-                    // record patch location for oop pointers
-                    hsData.constant = dataPatch.getConstant();
-                    patches[patchIndex++] = hsData;
-                }
-                dataPatch.externalData = hsData;
-
-                index += d.getSize(arch);
-                d.emit(arch, buffer);
-            }
-
-            this.sectionAlignment = alignment;
-        }
-    }
-
     public static class Comment {
 
         public final String text;
@@ -169,10 +60,10 @@
         }
     }
 
-    public HotSpotCompiledCode(Architecture arch, CompilationResult compResult) {
+    public HotSpotCompiledCode(TargetDescription target, CompilationResult compResult) {
         this.comp = compResult;
         sites = getSortedSites(compResult);
-        dataSection = new DataSection(arch, sites);
+        dataSection = new DataSection(target, sites);
         if (compResult.getExceptionHandlers().isEmpty()) {
             exceptionHandlers = null;
         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java	Thu Mar 20 13:50:21 2014 +0100
@@ -35,8 +35,8 @@
     public final int entryBCI;
     public final int id;
 
-    public HotSpotCompiledNmethod(Architecture arch, HotSpotResolvedJavaMethod method, CompilationResult compResult) {
-        super(arch, compResult);
+    public HotSpotCompiledNmethod(TargetDescription target, HotSpotResolvedJavaMethod method, CompilationResult compResult) {
+        super(target, compResult);
         this.method = method;
         this.entryBCI = compResult.getEntryBCI();
         this.id = compResult.getId();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Thu Mar 20 13:50:21 2014 +0100
@@ -26,7 +26,7 @@
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.code.CompilationResult.Infopoint;
-import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.data.*;
 import com.oracle.graal.hotspot.stubs.*;
 
 /**
@@ -38,8 +38,8 @@
 
     public final String stubName;
 
-    public HotSpotCompiledRuntimeStub(Architecture arch, Stub stub, CompilationResult compResult) {
-        super(arch, compResult);
+    public HotSpotCompiledRuntimeStub(TargetDescription target, Stub stub, CompilationResult compResult) {
+        super(target, compResult);
         assert checkStubInvariants(compResult);
         this.stubName = stub.toString();
     }
@@ -50,11 +50,7 @@
     private boolean checkStubInvariants(CompilationResult compResult) {
         assert compResult.getExceptionHandlers().isEmpty();
         for (DataPatch data : compResult.getDataReferences()) {
-            Constant constant = data.getConstant();
-            if (constant != null) {
-                assert constant.getKind() != Kind.Object : this + " cannot have embedded object constant: " + constant;
-                assert constant.getPrimitiveAnnotation() == null : this + " cannot have embedded metadata: " + constant;
-            }
+            assert !(data.data instanceof PatchedData) : this + " cannot have embedded object or metadata constant: " + data.data;
         }
         for (Infopoint infopoint : compResult.getInfopoints()) {
             assert infopoint instanceof Call : this + " cannot have non-call infopoint: " + infopoint;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu Mar 20 13:50:21 2014 +0100
@@ -235,6 +235,9 @@
         if (HotSpotPrintInlining.getValue() == false) {
             HotSpotPrintInlining.setValue(config.printInlining);
         }
+        if (HotSpotCIPrintCompilerName.getValue() == false) {
+            HotSpotCIPrintCompilerName.setValue(config.printCompilerName);
+        }
 
         if (Boolean.valueOf(System.getProperty("graal.printconfig"))) {
             printConfig(config);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.CodeUtil.RefMapFormatter;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.nodes.type.*;
+
+public class HotSpotReferenceMap implements ReferenceMap, Serializable {
+
+    private static final long serialVersionUID = -1052183095979496819L;
+
+    /**
+     * Contains 2 bits per register.
+     * <ul>
+     * <li>bit0 = 0: contains no references</li>
+     * <li>bit0 = 1, bit1 = 0: contains a wide oop</li>
+     * <li>bit0 = 1, bit1 = 1: contains a narrow oop</li>
+     * </ul>
+     */
+    private final BitSet registerRefMap;
+
+    /**
+     * Contains 3 bits per stack slot.
+     * <ul>
+     * <li>bit0 = 0: contains no references</li>
+     * <li>bit0 = 1, bit1+2 = 0: contains a wide oop</li>
+     * <li>bit0 = 1, bit1 = 1: contains a narrow oop in the lower half</li>
+     * <li>bit0 = 1, bit2 = 1: contains a narrow oop in the upper half</li>
+     * </ul>
+     */
+    private final BitSet frameRefMap;
+
+    private final int frameSlotSize;
+
+    public HotSpotReferenceMap(int registerCount, int frameSlotCount, int frameSlotSize) {
+        if (registerCount > 0) {
+            this.registerRefMap = new BitSet(registerCount * 2);
+        } else {
+            this.registerRefMap = null;
+        }
+        this.frameRefMap = new BitSet(frameSlotCount * 3);
+        this.frameSlotSize = frameSlotSize;
+    }
+
+    public void setRegister(int idx, PlatformKind kind) {
+        if (kind == Kind.Object) {
+            registerRefMap.set(2 * idx);
+        } else if (kind == NarrowOopStamp.NarrowOop) {
+            registerRefMap.set(2 * idx);
+            registerRefMap.set(2 * idx + 1);
+        }
+    }
+
+    public void setStackSlot(int offset, PlatformKind kind) {
+        int idx = offset / frameSlotSize;
+        if (kind == Kind.Object) {
+            assert offset % frameSlotSize == 0;
+            frameRefMap.set(3 * idx);
+        } else if (kind == NarrowOopStamp.NarrowOop) {
+            frameRefMap.set(3 * idx);
+            if (offset % frameSlotSize == 0) {
+                frameRefMap.set(3 * idx + 1);
+            } else {
+                assert offset % frameSlotSize == frameSlotSize / 2;
+                frameRefMap.set(3 * idx + 2);
+            }
+        }
+    }
+
+    public boolean hasRegisterRefMap() {
+        return registerRefMap != null && registerRefMap.size() > 0;
+    }
+
+    public boolean hasFrameRefMap() {
+        return frameRefMap != null && frameRefMap.size() > 0;
+    }
+
+    public void appendRegisterMap(StringBuilder sb, RefMapFormatter formatter) {
+        for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 2)) {
+            sb.append(' ').append(formatter.formatRegister(reg / 2));
+        }
+    }
+
+    public void appendFrameMap(StringBuilder sb, RefMapFormatter formatter) {
+        for (int slot = frameRefMap.nextSetBit(0); slot >= 0; slot = frameRefMap.nextSetBit(slot + 3)) {
+            sb.append(' ').append(formatter.formatStackSlot(slot / 3));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.nodes.type.*;
+
+public class HotSpotTargetDescription extends TargetDescription {
+
+    private final PlatformKind rawNarrowOopKind;
+
+    public HotSpotTargetDescription(Architecture arch, boolean isMP, int stackAlignment, int implicitNullCheckLimit, boolean inlineObjects, PlatformKind rawNarrowOopKind) {
+        super(arch, isMP, stackAlignment, implicitNullCheckLimit, inlineObjects);
+        this.rawNarrowOopKind = rawNarrowOopKind;
+    }
+
+    @Override
+    public int getSizeInBytes(PlatformKind kind) {
+        if (kind == NarrowOopStamp.NarrowOop) {
+            return super.getSizeInBytes(rawNarrowOopKind);
+        } else {
+            return super.getSizeInBytes(kind);
+        }
+    }
+
+    @Override
+    public ReferenceMap createReferenceMap(boolean hasRegisters, int stackSlotCount) {
+        return new HotSpotReferenceMap(hasRegisters ? arch.getRegisterReferenceMapBitCount() : 0, stackSlotCount, wordSize);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Mar 20 13:50:21 2014 +0100
@@ -709,10 +709,12 @@
     @HotSpotVMFlag(name = "DontCompileHugeMethods") @Stable public boolean dontCompileHugeMethods;
     @HotSpotVMFlag(name = "HugeMethodLimit") @Stable public int hugeMethodLimit;
     @HotSpotVMFlag(name = "PrintCompilation") @Stable public boolean printCompilation;
+    @HotSpotVMFlag(name = "CIPrintCompilerName") @Stable public boolean printCompilerName;
     @HotSpotVMFlag(name = "PrintInlining") @Stable public boolean printInlining;
     @HotSpotVMFlag(name = "GraalUseFastLocking") @Stable public boolean useFastLocking;
     @HotSpotVMFlag(name = "ForceUnreachable") @Stable public boolean forceUnreachable;
     @HotSpotVMFlag(name = "GPUOffload") @Stable public boolean gpuOffload;
+    @HotSpotVMFlag(name = "TieredCompilation") @Stable public boolean tieredCompilation;
 
     @HotSpotVMFlag(name = "UseTLAB") @Stable public boolean useTLAB;
     @HotSpotVMFlag(name = "UseBiasedLocking") @Stable public boolean useBiasedLocking;
@@ -1189,6 +1191,7 @@
     @HotSpotVMField(name = "MethodData::_data_size", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataDataSize;
     @HotSpotVMField(name = "MethodData::_data[0]", type = "intptr_t", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOopDataOffset;
     @HotSpotVMField(name = "MethodData::_trap_hist._array[0]", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOopTrapHistoryOffset;
+    @HotSpotVMField(name = "MethodData::_graal_node_count", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataGraalNodeCountOffset;
 
     @HotSpotVMField(name = "nmethod::_verified_entry_point", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable public int nmethodEntryOffset;
     @HotSpotVMField(name = "nmethod::_comp_level", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int nmethodCompLevelOffset;
@@ -1419,6 +1422,22 @@
     @HotSpotVMConstant(name = "CompilerToVM::KLASS_TAG") @Stable public int compilerToVMKlassTag;
     @HotSpotVMConstant(name = "CompilerToVM::SYMBOL_TAG") @Stable public int compilerToVMSymbolTag;
 
+    @HotSpotVMConstant(name = "CodeInstaller::VERIFIED_ENTRY") @Stable public int codeInstallerMarkIdVerifiedEntry;
+    @HotSpotVMConstant(name = "CodeInstaller::UNVERIFIED_ENTRY") @Stable public int codeInstallerMarkIdUnverifiedEntry;
+    @HotSpotVMConstant(name = "CodeInstaller::OSR_ENTRY") @Stable public int codeInstallerMarkIdOsrEntry;
+    @HotSpotVMConstant(name = "CodeInstaller::EXCEPTION_HANDLER_ENTRY") @Stable public int codeInstallerMarkIdExceptionHandlerEntry;
+    @HotSpotVMConstant(name = "CodeInstaller::DEOPT_HANDLER_ENTRY") @Stable public int codeInstallerMarkIdDeoptHandlerEntry;
+    @HotSpotVMConstant(name = "CodeInstaller::INVOKEINTERFACE") @Stable public int codeInstallerMarkIdInvokeinterface;
+    @HotSpotVMConstant(name = "CodeInstaller::INVOKEVIRTUAL") @Stable public int codeInstallerMarkIdInvokevirtual;
+    @HotSpotVMConstant(name = "CodeInstaller::INVOKESTATIC") @Stable public int codeInstallerMarkIdInvokestatic;
+    @HotSpotVMConstant(name = "CodeInstaller::INVOKESPECIAL") @Stable public int codeInstallerMarkIdInvokespecial;
+    @HotSpotVMConstant(name = "CodeInstaller::INLINE_INVOKE") @Stable public int codeInstallerMarkIdInlineInvoke;
+    @HotSpotVMConstant(name = "CodeInstaller::POLL_NEAR") @Stable public int codeInstallerMarkIdPollNear;
+    @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_NEAR") @Stable public int codeInstallerMarkIdPollReturnNear;
+    @HotSpotVMConstant(name = "CodeInstaller::POLL_FAR") @Stable public int codeInstallerMarkIdPollFar;
+    @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_FAR") @Stable public int codeInstallerMarkIdPollReturnFar;
+    @HotSpotVMConstant(name = "CodeInstaller::INVOKE_INVALID") @Stable public int codeInstallerMarkIdInvokeInvalid;
+
     public boolean check() {
         for (Field f : getClass().getDeclaredFields()) {
             int modifiers = f.getModifiers();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Mar 20 13:50:21 2014 +0100
@@ -252,14 +252,6 @@
     boolean hasFinalizableSubclass(long metaspaceKlass);
 
     /**
-     * Gets the compiled code size for a method.
-     * 
-     * @param metaspaceMethod the metaspace Method object to query
-     * @return the compiled code size the method
-     */
-    int getCompiledCodeSize(long metaspaceMethod);
-
-    /**
      * Gets the metaspace Method object corresponding to a given {@link Class} object and slot
      * number.
      * 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Mar 20 13:50:21 2014 +0100
@@ -111,9 +111,6 @@
     public native long getClassInitializer(long metaspaceKlass);
 
     @Override
-    public native int getCompiledCodeSize(long metaspaceMethod);
-
-    @Override
     public native long getMaxCallTargetOffset(long address);
 
     // The HotSpot disassembler seems not to be thread safe so it's better to synchronize its usage
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/Marks.java	Wed Mar 19 19:02:29 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.bridge;
-
-/**
- * Constants used to mark special positions in code being installed into the code cache by Graal C++
- * code. These constants need to be kept in sync with those of the same name defined in
- * graalCodeInstaller.hpp.
- */
-public interface Marks {
-
-    int MARK_VERIFIED_ENTRY = 1;
-    int MARK_UNVERIFIED_ENTRY = 2;
-    int MARK_OSR_ENTRY = 3;
-    int MARK_EXCEPTION_HANDLER_ENTRY = 4;
-    int MARK_DEOPT_HANDLER_ENTRY = 5;
-    int MARK_INVOKEINTERFACE = 6;
-    int MARK_INVOKEVIRTUAL = 7;
-    int MARK_INVOKESTATIC = 8;
-    int MARK_INVOKESPECIAL = 9;
-    int MARK_INLINE_INVOKE = 10;
-    int MARK_POLL_NEAR = 11;
-    int MARK_POLL_RETURN_NEAR = 12;
-    int MARK_POLL_FAR = 13;
-    int MARK_POLL_RETURN_FAR = 14;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/DataSection.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.data;
+
+import java.nio.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.CompilationResult.Data;
+import com.oracle.graal.api.code.CompilationResult.DataPatch;
+import com.oracle.graal.api.code.CompilationResult.Site;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.*;
+
+/**
+ * Represents the data section of a method.
+ */
+public final class DataSection {
+
+    /**
+     * The minimum alignment required for this data section.
+     */
+    public final int sectionAlignment;
+
+    /**
+     * The raw data contained in the data section.
+     */
+    public final byte[] data;
+
+    /**
+     * A list of locations where oop pointers need to be patched by the runtime.
+     */
+    public final DataPatch[] patches;
+
+    public DataSection(TargetDescription target, Site[] sites) {
+        int size = 0;
+        int patchCount = 0;
+        List<DataPatch> externalDataList = new ArrayList<>();
+
+        // find all external data items and determine total size of data section
+        for (Site site : sites) {
+            if (site instanceof DataPatch) {
+                DataPatch dataPatch = (DataPatch) site;
+                Data d = dataPatch.data;
+                if (dataPatch.inline) {
+                    assert d instanceof PatchedData : "unnecessary data patch";
+                } else {
+                    size = NumUtil.roundUp(size, d.getAlignment());
+                    size += d.getSize(target);
+                    externalDataList.add(dataPatch);
+                    if (d instanceof PatchedData) {
+                        patchCount++;
+                    }
+                }
+            }
+        }
+
+        data = new byte[size];
+        patches = new DataPatch[patchCount];
+        ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());
+        int index = 0;
+        int patchIndex = 0;
+        int alignment = 0;
+
+        // build data section
+        for (DataPatch dataPatch : externalDataList) {
+            assert !dataPatch.inline;
+            Data d = dataPatch.data;
+
+            alignment = Math.max(alignment, d.getAlignment());
+            index = NumUtil.roundUp(index, d.getAlignment());
+            buffer.position(index);
+
+            DataSectionReference reference = new DataSectionReference(index);
+            if (d instanceof PatchedData) {
+                // record patch location
+                patches[patchIndex++] = new DataPatch(index, d, true);
+            }
+            dataPatch.data = reference;
+
+            index += d.getSize(target);
+            d.emit(target, buffer);
+        }
+
+        this.sectionAlignment = alignment;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/DataSectionReference.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.data;
+
+import java.nio.*;
+
+import com.oracle.graal.api.code.CompilationResult.Data;
+import com.oracle.graal.api.code.CompilationResult.DataPatch;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Represents a reference to the data section. Before the code is installed, all {@link Data} items
+ * referenced by a {@link DataPatch} are put into the data section of the method, and replaced by
+ * {@link DataSectionReference}.
+ */
+public class DataSectionReference extends Data {
+
+    public final int offset;
+
+    protected DataSectionReference(int offset) {
+        super(0);
+        this.offset = offset;
+    }
+
+    @Override
+    public int getSize(TargetDescription target) {
+        return 0;
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.Illegal;
+    }
+
+    @Override
+    public void emit(TargetDescription target, ByteBuffer buffer) {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/MetaspaceData.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.data;
+
+import java.nio.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+
+/**
+ * A data item that represents a metaspace pointer.
+ */
+public class MetaspaceData extends PatchedData {
+
+    public final long value;
+    public final Object annotation;
+    public final boolean compressed;
+
+    public MetaspaceData(int alignment, long value, Object annotation, boolean compressed) {
+        super(alignment);
+        assert annotation != null;
+        this.value = value;
+        this.annotation = annotation;
+        this.compressed = compressed;
+    }
+
+    @Override
+    public int getSize(TargetDescription target) {
+        if (compressed) {
+            return target.getSizeInBytes(Kind.Int);
+        } else {
+            return target.getSizeInBytes(target.wordKind);
+        }
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.Long;
+    }
+
+    @Override
+    public void emit(TargetDescription target, ByteBuffer buffer) {
+        switch (getSize(target)) {
+            case 4:
+                buffer.putInt((int) value);
+                break;
+            case 8:
+                buffer.putLong(value);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("unexpected metaspace pointer size");
+        }
+    }
+
+    @Override
+    public String toString() {
+        return (compressed ? "NarrowPointer[0x" + Integer.toHexString((int) value) : "Pointer[0x" + Long.toHexString(value)) + "]{" + annotation + "}";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.data;
+
+import java.nio.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.nodes.type.*;
+
+/**
+ * A data item that represents an oop value.
+ */
+public class OopData extends PatchedData {
+
+    public final Object object;
+    public final boolean compressed;
+
+    public OopData(int alignment, Object object, boolean compressed) {
+        super(alignment);
+        this.object = object;
+        this.compressed = compressed;
+    }
+
+    @Override
+    public int getSize(TargetDescription target) {
+        if (compressed) {
+            return target.getSizeInBytes(NarrowOopStamp.NarrowOop);
+        } else {
+            return target.getSizeInBytes(Kind.Object);
+        }
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.Object;
+    }
+
+    @Override
+    public void emit(TargetDescription target, ByteBuffer buffer) {
+        switch (getSize(target)) {
+            case 4:
+                buffer.putInt(0xDEADDEAD);
+                break;
+            case 8:
+                buffer.putLong(0xDEADDEADDEADDEADL);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("unexpected oop size");
+        }
+    }
+
+    @Override
+    public String toString() {
+        return (compressed ? "NarrowOop[" : "Oop[") + Kind.Object.format(object) + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/PatchedData.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.data;
+
+import com.oracle.graal.api.code.CompilationResult.Data;
+
+/**
+ * Represents a data item that needs to be patched.
+ */
+public abstract class PatchedData extends Data {
+
+    protected PatchedData(int alignment) {
+        super(alignment);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Thu Mar 20 13:50:21 2014 +0100
@@ -50,10 +50,10 @@
  * infrastructure is enabled by specifying either the GenericDynamicCounters or
  * BenchmarkDynamicCounters option.<br/>
  * 
- * The counters are kept in a special area in the native JavaThread object, and the number of
- * counters is configured in {@code thread.hpp (GRAAL_COUNTERS_SIZE)}. This file also contains an
- * option to exclude compiler threads ({@code GRAAL_COUNTERS_EXCLUDE_COMPILER_THREADS}, which
- * defaults to true).
+ * The counters are kept in a special area allocated for each native JavaThread object, and the
+ * number of counters is configured using {@code -XX:GraalCounterSize=value}.
+ * {@code -XX:+/-GraalCountersExcludeCompiler} configures whether to exclude compiler threads
+ * (defaults to true).
  * 
  * The subsystems that use the logging need to have their own options to turn on the counters, and
  * insert DynamicCounterNodes when they're enabled.
@@ -64,12 +64,10 @@
  * <h1>Example</h1> In order to create statistics about allocations within the DaCapo pmd benchmark
  * the following steps are necessary:
  * <ul>
- * <li>Modify {@code thread.hpp}: increase GRAAL_COUNTER_SIZE. The actual required value depends on
- * the granularity of the profiling, 10000 should be enough for most cases. This will increase the
- * JavaThread structure by 80kb.</li>
- * <li>Also in {@code thread.hpp}: GRAAL_COUNTERS_EXCLUDE_COMPILER_THREADS specifies whether the
- * numbers generated by compiler threads should be excluded (default: true).</li>
- * <li>Build the Graal VM.</li>
+ * <li>Set {@code -XX:GraalCounterSize=value}. The actual required value depends on the granularity
+ * of the profiling, 10000 should be enough for most cases.</li>
+ * <li>Also: {@code -XX:+/-GraalCountersExcludeCompiler} specifies whether the numbers generated by
+ * compiler threads should be excluded (default: true).</li>
  * <li>Start the DaCapo pmd benchmark with
  * {@code "-G:BenchmarkDynamicCounters=err, starting ====, PASSED in "} and
  * {@code -G:+ProfileAllocations}.</li>
@@ -330,7 +328,7 @@
 
             int index = BenchmarkCounters.getIndex(counter);
             if (index >= config.graalCountersSize) {
-                throw new GraalInternalError("too many counters, reduce number of counters or increase GRAAL_COUNTERS_SIZE (current value: " + config.graalCountersSize + ")");
+                throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")");
             }
             ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, config.graalCountersThreadOffset, graph);
             ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE, false));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java	Thu Mar 20 13:50:21 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.logging;
 
+import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
@@ -94,16 +95,15 @@
         }
     }
 
-    // CheckStyle: stop system..print check
     protected void print() {
         long sum = 0;
+        PrintStream out = System.out;
         for (Map.Entry<Method, AtomicLong> entry : calls.entrySet()) {
             Method method = entry.getKey();
             long count = entry.getValue().get();
             sum += count;
-            System.out.println(delegate.getClass().getSimpleName() + "." + method.getName() + ": " + count);
+            out.println(delegate.getClass().getSimpleName() + "." + method.getName() + ": " + count);
         }
-        System.out.println(delegate.getClass().getSimpleName() + " calls: " + sum);
+        out.println(delegate.getClass().getSimpleName() + " calls: " + sum);
     }
-    // CheckStyle: resume system..print check
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Thu Mar 20 13:50:21 2014 +0100
@@ -29,15 +29,20 @@
 import com.oracle.graal.api.code.CodeUtil.DefaultRefMapFormatter;
 import com.oracle.graal.api.code.CodeUtil.RefMapFormatter;
 import com.oracle.graal.api.code.CompilationResult.Call;
+import com.oracle.graal.api.code.CompilationResult.Data;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.api.code.CompilationResult.Mark;
+import com.oracle.graal.api.code.CompilationResult.PrimitiveData;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
+import com.oracle.graal.hotspot.data.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.printer.*;
 
 /**
@@ -57,6 +62,54 @@
 
     protected abstract RegisterConfig createRegisterConfig();
 
+    /**
+     * Constants used to mark special positions in code being installed into the code cache by Graal
+     * C++ code.
+     */
+    public enum MarkId {
+        VERIFIED_ENTRY(config().codeInstallerMarkIdVerifiedEntry),
+        UNVERIFIED_ENTRY(config().codeInstallerMarkIdUnverifiedEntry),
+        OSR_ENTRY(config().codeInstallerMarkIdOsrEntry),
+        EXCEPTION_HANDLER_ENTRY(config().codeInstallerMarkIdExceptionHandlerEntry),
+        DEOPT_HANDLER_ENTRY(config().codeInstallerMarkIdDeoptHandlerEntry),
+        INVOKEINTERFACE(config().codeInstallerMarkIdInvokeinterface),
+        INVOKEVIRTUAL(config().codeInstallerMarkIdInvokevirtual),
+        INVOKESTATIC(config().codeInstallerMarkIdInvokestatic),
+        INVOKESPECIAL(config().codeInstallerMarkIdInvokespecial),
+        INLINE_INVOKE(config().codeInstallerMarkIdInlineInvoke),
+        POLL_NEAR(config().codeInstallerMarkIdPollNear),
+        POLL_RETURN_NEAR(config().codeInstallerMarkIdPollReturnNear),
+        POLL_FAR(config().codeInstallerMarkIdPollFar),
+        POLL_RETURN_FAR(config().codeInstallerMarkIdPollReturnFar);
+
+        private final int value;
+
+        private MarkId(int value) {
+            this.value = value;
+        }
+
+        private static HotSpotVMConfig config() {
+            return HotSpotGraalRuntime.runtime().getConfig();
+        }
+
+        public static MarkId getEnum(int value) {
+            for (MarkId e : values()) {
+                if (e.value == value) {
+                    return e;
+                }
+            }
+            throw GraalInternalError.shouldNotReachHere("unknown enum value " + value);
+        }
+
+        /**
+         * Helper method to {@link CompilationResultBuilder#recordMark(Object) record a mark} with a
+         * {@link CompilationResultBuilder}.
+         */
+        public static void recordMark(CompilationResultBuilder crb, MarkId mark) {
+            crb.recordMark(mark.value);
+        }
+    }
+
     @Override
     public String disassemble(CompilationResult compResult, InstalledCode installedCode) {
         byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode();
@@ -82,10 +135,10 @@
                 }
             }
             for (DataPatch site : compResult.getDataReferences()) {
-                hcf.addOperandComment(site.pcOffset, "{" + site.getDataString() + "}");
+                hcf.addOperandComment(site.pcOffset, "{" + site.data.toString() + "}");
             }
             for (Mark mark : compResult.getMarks()) {
-                hcf.addComment(mark.pcOffset, getMarkName(mark));
+                hcf.addComment(mark.pcOffset, MarkId.getEnum((int) mark.id).toString());
             }
         }
         return hcf.toEmbeddedString();
@@ -111,25 +164,6 @@
         return String.valueOf(call.target);
     }
 
-    /**
-     * Decodes a mark to a mnemonic if possible.
-     */
-    private static String getMarkName(Mark mark) {
-        Field[] fields = Marks.class.getDeclaredFields();
-        for (Field f : fields) {
-            if (Modifier.isStatic(f.getModifiers()) && f.getName().startsWith("MARK_")) {
-                f.setAccessible(true);
-                try {
-                    if (f.get(null).equals(mark.id)) {
-                        return f.getName();
-                    }
-                } catch (Exception e) {
-                }
-            }
-        }
-        return "MARK:" + mark.id;
-    }
-
     private static void addExceptionHandlersComment(CompilationResult compResult, HexCodeFile hcf) {
         if (!compResult.getExceptionHandlers().isEmpty()) {
             String nl = HexCodeFile.NEW_LINE;
@@ -173,7 +207,7 @@
             compResult.setId(method.allocateCompileId(compResult.getEntryBCI()));
         }
         HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), true);
-        runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target.arch, method, compResult), installedCode, method.getSpeculationLog());
+        runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target, method, compResult), installedCode, method.getSpeculationLog());
         return logOrDump(installedCode, compResult);
     }
 
@@ -184,7 +218,7 @@
             compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI()));
         }
         HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
-        CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target.arch, hotspotMethod, compResult), code, log);
+        CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target, hotspotMethod, compResult), code, log);
         if (result != CodeInstallResult.OK) {
             return null;
         }
@@ -203,7 +237,7 @@
             compResult.setId(javaMethod.allocateCompileId(compResult.getEntryBCI()));
         }
         HotSpotNmethod code = new HotSpotNmethod(javaMethod, compResult.getName(), false, true);
-        HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(target.arch, javaMethod, compResult);
+        HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(target, javaMethod, compResult);
         CompilerToVM vm = runtime.getCompilerToVM();
         CodeInstallResult result = vm.installCode(compiled, code, null);
         if (result != CodeInstallResult.OK) {
@@ -216,6 +250,16 @@
         return constant.getPrimitiveAnnotation() != null;
     }
 
+    public Data createDataItem(Constant constant, int alignment) {
+        if (constant.getPrimitiveAnnotation() != null) {
+            return new MetaspaceData(alignment, constant.asLong(), constant.getPrimitiveAnnotation(), false);
+        } else if (constant.getKind().isObject()) {
+            return new OopData(alignment, constant.asObject(), false);
+        } else {
+            return new PrimitiveData(constant, alignment);
+        }
+    }
+
     @Override
     public TargetDescription getTarget() {
         return target;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Thu Mar 20 13:50:21 2014 +0100
@@ -700,9 +700,9 @@
 
     public int getScalingFactor(Kind kind) {
         if (useCompressedOops() && kind == Kind.Object) {
-            return this.runtime.getTarget().arch.getSizeInBytes(Kind.Int);
+            return this.runtime.getTarget().getSizeInBytes(Kind.Int);
         } else {
-            return this.runtime.getTarget().arch.getSizeInBytes(kind);
+            return this.runtime.getTarget().getSizeInBytes(kind);
         }
     }
 
@@ -757,7 +757,7 @@
         ValueNode arrayLength = readArrayLength(n.graph(), array, tool.getConstantReflection());
         if (arrayLength == null) {
             Stamp stamp = StampFactory.positiveInt();
-            ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, g), stamp, BarrierType.NONE, false));
+            ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, g), stamp, BarrierType.NONE, false));
             g.addBeforeFixed(n, readArrayLength);
             readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool));
             arrayLength = readArrayLength;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Thu Mar 20 13:50:21 2014 +0100
@@ -299,7 +299,7 @@
                     ResolvedJavaType elementType = lookupJavaType.getComponentType();
                     Kind elementKind = elementType.getKind();
                     final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind);
-                    int sizeOfElement = HotSpotGraalRuntime.runtime().getTarget().arch.getSizeInBytes(elementKind);
+                    int sizeOfElement = HotSpotGraalRuntime.runtime().getTarget().getSizeInBytes(elementKind);
                     int alignment = HotSpotGraalRuntime.runtime().getTarget().wordSize;
                     int log2ElementSize = CodeUtil.log2(sizeOfElement);
                     return NewObjectSnippets.computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java	Thu Mar 20 13:50:21 2014 +0100
@@ -23,11 +23,15 @@
 package com.oracle.graal.hotspot.meta;
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.debug.Debug.*;
+import static java.util.FormattableFlags.*;
+
+import java.util.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 
-public abstract class HotSpotMethod extends CompilerObject implements JavaMethod {
+public abstract class HotSpotMethod extends CompilerObject implements JavaMethod, Formattable {
 
     private static final long serialVersionUID = 7167491397941960839L;
     protected String name;
@@ -54,4 +58,9 @@
         String fmt = String.format("HotSpotMethod<%%%c.%%n(%%p)%s>", h, suffix);
         return format(fmt, this);
     }
+
+    public void formatTo(Formatter formatter, int flags, int width, int precision) {
+        String base = (flags & ALTERNATE) == ALTERNATE ? getName() : toString();
+        formatter.format(applyFormattingFlagsAndWidth(base, flags & ~ALTERNATE, width));
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Thu Mar 20 13:50:21 2014 +0100
@@ -825,4 +825,12 @@
             super(runtime().getConfig().dataLayoutArgInfoDataTag, ARG_INFO_DATA_SIZE);
         }
     }
+
+    public void setCompiledGraphSize(int nodeCount) {
+        unsafe.putInt(metaspaceMethodData + config.methodDataGraalNodeCountOffset, nodeCount);
+    }
+
+    public int getCompiledGraphSize() {
+        return unsafe.getInt(metaspaceMethodData + config.methodDataGraalNodeCountOffset);
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Thu Mar 20 13:50:21 2014 +0100
@@ -43,7 +43,12 @@
 
     private static final long serialVersionUID = -1784683588947054103L;
 
+    /**
+     * This (indirect) Method* reference is safe since class redefinition preserves all methods
+     * associated with nmethods in the code cache.
+     */
     private final HotSpotResolvedJavaMethod method;
+
     private final boolean isDefault;
     private final boolean isExternal;
     private final String name;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java	Thu Mar 20 13:50:21 2014 +0100
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodes.*;
 
 public final class HotSpotProfilingInfo extends CompilerObject implements ProfilingInfo {
 
@@ -205,4 +206,21 @@
     public void setMature() {
         isMature = true;
     }
+
+    @Override
+    public boolean setCompilerIRSize(Class<?> irType, int size) {
+        if (irType == StructuredGraph.class) {
+            methodData.setCompiledGraphSize(size);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public int getCompilerIRSize(Class<?> irType) {
+        if (irType == StructuredGraph.class) {
+            return methodData.getCompiledGraphSize();
+        }
+        return -1;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu Mar 20 13:50:21 2014 +0100
@@ -28,8 +28,6 @@
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
-import java.util.*;
-import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -59,7 +57,6 @@
     private boolean forceInline;
     private boolean dontInline;
     private boolean ignoredBySecurityStackWalk;
-    private Map<Object, Object> compilerStorage;
     private HotSpotMethodData methodData;
     private byte[] code;
     private SpeculationLog speculationLog;
@@ -356,10 +353,6 @@
         return signature;
     }
 
-    public int getCompiledCodeSize() {
-        return runtime().getCompilerToVM().getCompiledCodeSize(metaspaceMethod);
-    }
-
     /**
      * Gets the value of {@code Method::_code}.
      * 
@@ -380,9 +373,8 @@
     }
 
     /**
-     * Gets the compilation level of the currently installed code for this method.
-     * 
-     * @return compilation level
+     * @param level
+     * @return true if the currently installed code was generated at {@code level}.
      */
     public boolean hasCompiledCodeAtLevel(int level) {
         long compiledCode = getCompiledCode();
@@ -433,14 +425,6 @@
     }
 
     @Override
-    public Map<Object, Object> getCompilerStorage() {
-        if (compilerStorage == null) {
-            compilerStorage = new ConcurrentHashMap<>();
-        }
-        return compilerStorage;
-    }
-
-    @Override
     public ConstantPool getConstantPool() {
         return constantPool;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Thu Mar 20 13:50:21 2014 +0100
@@ -363,6 +363,10 @@
     @Override
     public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) {
         assert method instanceof HotSpotMethod;
+        if (!isAbstract(method.getModifiers()) && method.getDeclaringClass().equals(this)) {
+            return method;
+        }
+
         final long resolvedMetaspaceMethod = runtime().getCompilerToVM().resolveMethod(metaspaceKlass(), method.getName(), ((HotSpotSignature) method.getSignature()).getMethodDescriptor());
         if (resolvedMetaspaceMethod == 0) {
             return null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes.type;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class NarrowOopStamp extends ObjectStamp {
+
+    public static final PlatformKind NarrowOop = new PlatformKind() {
+
+        public String name() {
+            return "NarrowOop";
+        }
+
+        @Override
+        public String toString() {
+            return name();
+        }
+    };
+
+    private final CompressEncoding encoding;
+
+    public NarrowOopStamp(ObjectStamp stamp, CompressEncoding encoding) {
+        this(stamp.type(), stamp.isExactType(), stamp.nonNull(), stamp.alwaysNull(), encoding);
+    }
+
+    public NarrowOopStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull, CompressEncoding encoding) {
+        super(type, exactType, nonNull, alwaysNull);
+        this.encoding = encoding;
+    }
+
+    public Stamp uncompressed() {
+        return new ObjectStamp(type(), isExactType(), nonNull(), alwaysNull());
+    }
+
+    public CompressEncoding getEncoding() {
+        return encoding;
+    }
+
+    @Override
+    public Stamp unrestricted() {
+        return new NarrowOopStamp((ObjectStamp) super.unrestricted(), encoding);
+    }
+
+    @Override
+    public Kind getStackKind() {
+        return Kind.Object;
+    }
+
+    @Override
+    public PlatformKind getPlatformKind(LIRTypeTool tool) {
+        return NarrowOop;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        str.append('n');
+        str.append(super.toString());
+        return str.toString();
+    }
+
+    @Override
+    public Stamp meet(Stamp otherStamp) {
+        if (this == otherStamp) {
+            return this;
+        }
+        if (otherStamp instanceof IllegalStamp) {
+            return otherStamp.meet(this);
+        }
+        if (!isCompatible(otherStamp)) {
+            return StampFactory.illegal(Kind.Illegal);
+        }
+        return new NarrowOopStamp((ObjectStamp) super.meet(otherStamp), encoding);
+    }
+
+    @Override
+    public Stamp join(Stamp otherStamp) {
+        if (this == otherStamp) {
+            return this;
+        }
+        if (otherStamp instanceof IllegalStamp) {
+            return otherStamp.join(this);
+        }
+        if (!isCompatible(otherStamp)) {
+            return StampFactory.illegal(Kind.Illegal);
+        }
+        return new NarrowOopStamp((ObjectStamp) super.join(otherStamp), encoding);
+    }
+
+    @Override
+    public boolean isCompatible(Stamp other) {
+        if (this == other) {
+            return true;
+        }
+        if (other instanceof NarrowOopStamp) {
+            NarrowOopStamp narrow = (NarrowOopStamp) other;
+            return encoding.equals(narrow.encoding);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + encoding.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        NarrowOopStamp other = (NarrowOopStamp) obj;
+        if (!encoding.equals(other.encoding)) {
+            return false;
+        }
+        return super.equals(other);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Thu Mar 20 13:50:21 2014 +0100
@@ -73,11 +73,11 @@
             Node currentNode = iterator.next();
             assert !isSafepoint(currentNode) : "Write barrier must be present " + write;
             if (useG1GC()) {
-                if (!(currentNode instanceof G1PostWriteBarrier) || ((currentNode instanceof G1PostWriteBarrier) && !validateBarrier((FixedAccessNode) write, (WriteBarrier) currentNode))) {
+                if (!(currentNode instanceof G1PostWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (WriteBarrier) currentNode))) {
                     expandFrontier(frontier, currentNode);
                 }
             } else {
-                if (!(currentNode instanceof SerialWriteBarrier) || ((currentNode instanceof SerialWriteBarrier) && !validateBarrier((FixedAccessNode) write, (WriteBarrier) currentNode)) ||
+                if (!(currentNode instanceof SerialWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (WriteBarrier) currentNode)) ||
                                 ((currentNode instanceof SerialWriteBarrier) && !validateBarrier((FixedAccessNode) write, (WriteBarrier) currentNode))) {
                     expandFrontier(frontier, currentNode);
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java	Thu Mar 20 13:50:21 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, 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
@@ -31,16 +31,16 @@
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.*;
 import com.oracle.graal.word.*;
 
 /**
- * Stub called by the {@linkplain Marks#MARK_EXCEPTION_HANDLER_ENTRY exception handler entry point}
- * in a compiled method. This entry point is used when returning to a method to handle an exception
+ * Stub called by the {@linkplain MarkId#EXCEPTION_HANDLER_ENTRY exception handler entry point} in a
+ * compiled method. This entry point is used when returning to a method to handle an exception
  * thrown by a callee. It is not used for routing implicit exceptions. Therefore, it does not need
  * to save any registers as HotSpot uses a caller save convention.
  * <p>
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Thu Mar 20 13:50:21 2014 +0100
@@ -153,7 +153,7 @@
                 try (Scope s = Debug.scope("CodeInstall")) {
                     Stub stub = Stub.this;
                     HotSpotRuntimeStub installedCode = new HotSpotRuntimeStub(stub);
-                    HotSpotCompiledCode hsCompResult = new HotSpotCompiledRuntimeStub(backend.getTarget().arch, stub, compResult);
+                    HotSpotCompiledCode hsCompResult = new HotSpotCompiledRuntimeStub(backend.getTarget(), stub, compResult);
 
                     CodeInstallResult result = runtime().getCompilerToVM().installCode(hsCompResult, installedCode, null);
                     if (result != CodeInstallResult.OK) {
--- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Thu Mar 20 13:50:21 2014 +0100
@@ -168,7 +168,7 @@
         Kind kind = arg.getKind();
         if (kind == Kind.Double || kind == Kind.Long) {
             regPrefix = "$d";
-        } else if (kind == Kind.Int || kind == Kind.Float || kind == Kind.NarrowOop) {
+        } else if (kind == Kind.Int || kind == Kind.Float) {
             regPrefix = "$s";
         } else {
             regPrefix = "$d";
@@ -193,7 +193,6 @@
                 case Int:
                 case Long:
                 case Object:
-                case NarrowOop:
                     return true;
             }
         } else if (category == FPU) {
--- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java	Thu Mar 20 13:50:21 2014 +0100
@@ -24,7 +24,6 @@
 package com.oracle.graal.hsail;
 
 import com.oracle.graal.api.code.*;
-
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
@@ -123,7 +122,7 @@
 
             if (locations[i] == null) {
                 locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out);
-                currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize);
+                currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize);
             }
         }
 
@@ -150,7 +149,6 @@
             case Short:
             case Byte:
             case Float:
-            case NarrowOop:
                 return regBitness32.clone();
             case Long:
             case Double:
@@ -169,6 +167,11 @@
     }
 
     @Override
+    public boolean areAllAllocatableRegistersCallerSaved() {
+        return false;
+    }
+
+    @Override
     public CalleeSaveLayout getCalleeSaveLayout() {
         return null;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/DecompilerTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,111 @@
+/*
+ * 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.java.decompiler.test;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.java.decompiler.test.example.*;
+import com.oracle.graal.printer.*;
+import com.oracle.graal.runtime.*;
+
+@Ignore
+public class DecompilerTest {
+
+    public static void doTest(String name) {
+        try {
+            DebugEnvironment.initialize(System.out);
+            MetaAccessProvider metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess();
+            Method method = Example.class.getDeclaredMethod(name, new Class[]{int.class, int.class});
+            final ResolvedJavaMethod javaMethod = metaAccess.lookupJavaMethod(method);
+            TestUtil.compileMethod(javaMethod);
+        } catch (NoSuchMethodException e) {
+            Assert.fail();
+        } catch (SecurityException e) {
+            Assert.fail();
+        }
+    }
+
+    @Test
+    public void test01() {
+        doTest("loop7");
+    }
+
+    @Test
+    public void test02() {
+        doTest("loop6");
+    }
+
+    @Test
+    public void test03() {
+        doTest("loop5");
+    }
+
+    @Test
+    public void test04() {
+        doTest("loop4");
+    }
+
+    @Test
+    public void test05() {
+        doTest("loop3");
+    }
+
+    @Test
+    public void test06() {
+        doTest("loop2");
+    }
+
+    @Test
+    public void test07() {
+        doTest("loop");
+    }
+
+    @Test
+    public void test08() {
+        doTest("if0");
+    }
+
+    @Test
+    public void test09() {
+        doTest("if1");
+    }
+
+    @Test
+    public void test10() {
+        doTest("if2");
+    }
+
+    @Test
+    public void test11() {
+        doTest("if3");
+    }
+
+    @Test
+    public void test12() {
+        doTest("if4");
+    }
+}
--- a/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java	Wed Mar 19 19:02:29 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * 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.java.decompiler.test;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.java.decompiler.test.example.*;
-import com.oracle.graal.printer.*;
-import com.oracle.graal.runtime.*;
-
-public class Test {
-
-    /**
-     * @param args
-     * @throws SecurityException
-     * @throws NoSuchMethodException
-     */
-    public static void main(String[] args) throws NoSuchMethodException, SecurityException {
-        DebugEnvironment.initialize(System.out);
-        MetaAccessProvider metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess();
-        Method method = Example.class.getDeclaredMethod("loop7", new Class[]{int.class, int.class});
-        final ResolvedJavaMethod javaMethod = metaAccess.lookupJavaMethod(method);
-        TestUtil.compileMethod(javaMethod);
-    }
-}
--- a/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java	Thu Mar 20 13:50:21 2014 +0100
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.compiler.GraalCompiler.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
--- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerIfSimplify.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerIfSimplify.java	Thu Mar 20 13:50:21 2014 +0100
@@ -68,7 +68,7 @@
                         // TODO(mg)
                         // thenBlocks and elseBlocks can be both empty --> causes an AssertionError
                         DecompilerIfBlock ifBlock = new DecompilerIfBlock(block.getBlock(), decompiler, thenBlocks, elseBlocks, infoStream);
-                        if (thenBlocks.contains(block.getBlock()) || elseBlocks.contains(block.getBlock())) {
+                        if (thenBlocks.contains(block) || elseBlocks.contains(block)) {
                             throw new AssertionError();
                         }
                         blocks.add(ifBlock);
--- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerIfBlock.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerIfBlock.java	Thu Mar 20 13:50:21 2014 +0100
@@ -158,7 +158,20 @@
 
     @Override
     public boolean contains(Block b) {
-        return b == block || thenBranch.contains(b) || elseBranch.contains(b);
+        if (b == block) {
+            return true;
+        }
+        for (DecompilerBlock i : thenBranch) {
+            if (i.block == b) {
+                return true;
+            }
+        }
+        for (DecompilerBlock i : elseBranch) {
+            if (i.block == b) {
+                return true;
+            }
+        }
+        return false;
     }
 
     @Override
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Mar 20 13:50:21 2014 +0100
@@ -748,7 +748,7 @@
                     int blockID = block.blockID;
                     // log statements in IFs because debugLiveX creates a new String
                     if (Debug.isLogEnabled()) {
-                        Debug.log("  start B%d  [%d, %d]  in: %s  out: %s  gen: %s  kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID),
+                        Debug.logv("  start B%d  [%d, %d]  in: %s  out: %s  gen: %s  kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID),
                                         debugLiveGen(blockID), debugLiveKill(blockID));
                     }
 
@@ -767,7 +767,7 @@
                     if (blockChanged) {
                         updateLiveness(blockID);
                         if (Debug.isLogEnabled()) {
-                            Debug.log("  end   B%d  [%d, %d]  in: %s  out: %s  gen: %s  kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID),
+                            Debug.logv("  end   B%d  [%d, %d]  in: %s  out: %s  gen: %s  kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID),
                                             debugLiveGen(blockID), debugLiveKill(blockID));
                         }
                     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Mar 20 13:50:21 2014 +0100
@@ -70,7 +70,7 @@
     public static final class RuntimeCalls {
 
         public static final ForeignCallDescriptor CREATE_NULL_POINTER_EXCEPTION = new ForeignCallDescriptor("createNullPointerException", NullPointerException.class);
-        public static final ForeignCallDescriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new ForeignCallDescriptor("createOutOfBoundsException", IndexOutOfBoundsException.class, int.class);
+        public static final ForeignCallDescriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new ForeignCallDescriptor("createOutOfBoundsException", ArrayIndexOutOfBoundsException.class, int.class);
     }
 
     /**
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Thu Mar 20 13:50:21 2014 +0100
@@ -204,7 +204,7 @@
                 return null;
             }
 
-            PhiNode phi = graph.addWithoutUnique(new PhiNode(currentValue.getKind(), block));
+            PhiNode phi = graph.addWithoutUnique(new PhiNode(currentValue.stamp().unrestricted(), block));
             for (int i = 0; i < block.phiPredecessorCount(); i++) {
                 phi.addInput(currentValue);
             }
@@ -302,7 +302,7 @@
         }
         assert !block.isPhiAtMerge(value) : "phi function for this block already created";
 
-        PhiNode phi = graph.addWithoutUnique(new PhiNode(value.getKind(), block));
+        PhiNode phi = graph.addWithoutUnique(new PhiNode(value.stamp().unrestricted(), block));
         phi.addInput(value);
         return phi;
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java	Thu Mar 20 13:50:21 2014 +0100
@@ -46,19 +46,18 @@
         return sum;
     }
 
-    // CheckStyle: stop system..print check
     private static void doPrint(int n) {
+        PrintStream out = System.out;
         for (int i = 0; i < n; i++) {
-            System.out.print('x');
+            out.print('x');
         }
     }
 
     public static void main(String[] args) throws Exception {
-        System.out.println(test(10000));
+        PrintStream out = System.out;
+        out.println(test(10000));
     }
 
-    // CheckStyle: resume system..print check
-
     @LongTest
     public void run0() throws Throwable {
         runTest("test", 10000);
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java	Thu Mar 20 13:50:21 2014 +0100
@@ -27,6 +27,25 @@
 
 public class LoopParseLong extends JTTTest {
 
+    @SuppressWarnings("unused")
+    public static long testShortened(String s, int radix) throws NumberFormatException {
+        long result = 0;
+        boolean negative = false;
+        int len = s.length();
+        char firstChar = s.charAt(0);
+        if (firstChar < '0') {
+            if (firstChar == '-') {
+                negative = true;
+            } else if (firstChar != '+') {
+                throw new NumberFormatException();
+            }
+            if (len == 1) {
+                throw new NumberFormatException();
+            }
+        }
+        return result;
+    }
+
     public static long test(String s, int radix) throws NumberFormatException {
         if (s == null) {
             throw new NumberFormatException("null");
@@ -81,6 +100,8 @@
 
     @LongTest
     public void run0() throws Throwable {
+        runTest("testShortened", "7", 10);
+        runTest("testShortened", "-100", 10);
         runTest("test", "7", 10);
         runTest("test", "-100", 10);
     }
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Thu Mar 20 13:50:21 2014 +0100
@@ -237,13 +237,6 @@
                         throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to object ref");
                     }
                     break;
-                case NarrowOop:
-                    if (input.isNull()) {
-                        masm.emitStoreImmediate(kind, 0L, address.toAddress());
-                    } else {
-                        throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to object ref");
-                    }
-                    break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Thu Mar 20 13:50:21 2014 +0100
@@ -170,7 +170,7 @@
             // Without this, frameNeedsAllocating() would never return true.
             int total = 0;
             for (StackSlot s : freedSlots) {
-                total += target.arch.getSizeInBytes(s.getKind());
+                total += target.getSizeInBytes(s.getKind());
             }
             if (total == spillSize - initialSpillSize) {
                 // reset spill area size
@@ -256,7 +256,7 @@
      * @return the size in bytes
      */
     protected int spillSlotSize(PlatformKind kind) {
-        return target.arch.getSizeInBytes(kind);
+        return target.getSizeInBytes(kind);
     }
 
     /**
@@ -347,8 +347,8 @@
         }
     }
 
-    public ReferenceMap initReferenceMap(boolean canHaveRegisters) {
-        ReferenceMap refMap = new ReferenceMap(canHaveRegisters ? target.arch.getRegisterReferenceMapBitCount() : 0, frameSize() / target.wordSize);
+    public ReferenceMap initReferenceMap(boolean hasRegisters) {
+        ReferenceMap refMap = target.createReferenceMap(hasRegisters, frameSize() / target.wordSize);
         for (StackSlot slot : objectStackSlots) {
             setReference(slot, refMap);
         }
@@ -364,22 +364,14 @@
      * @param refMap A reference map, as created by {@link #initReferenceMap(boolean)}.
      */
     public void setReference(Value location, ReferenceMap refMap) {
-        Kind kind = location.getKind();
-        if (kind == Kind.Object || kind == Kind.NarrowOop) {
-            if (isRegister(location)) {
-                refMap.setRegister(asRegister(location).number, kind == Kind.NarrowOop);
-            } else if (isStackSlot(location)) {
-                if (kind == Kind.NarrowOop) {
-                    int offset = offsetForStackSlot(asStackSlot(location));
-                    assert offset % target.wordSize == 0 || offset % target.wordSize == target.wordSize / 2;
-                    refMap.setStackSlot(offset / target.wordSize, offset % target.wordSize == 0, offset % target.wordSize != 0);
-                } else {
-                    int index = indexForStackSlot(asStackSlot(location));
-                    refMap.setStackSlot(index, false, false);
-                }
-            } else {
-                assert isConstant(location);
-            }
+        PlatformKind kind = location.getPlatformKind();
+        if (isRegister(location)) {
+            refMap.setRegister(asRegister(location).number, kind);
+        } else if (isStackSlot(location)) {
+            int offset = offsetForStackSlot(asStackSlot(location));
+            refMap.setStackSlot(offset, kind);
+        } else {
+            assert isConstant(location);
         }
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Thu Mar 20 13:50:21 2014 +0100
@@ -27,7 +27,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CompilationResult.ConstantData;
 import com.oracle.graal.api.code.CompilationResult.Data;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
@@ -157,6 +156,10 @@
     }
 
     public void recordInlineDataInCode(Constant data) {
+        recordInlineDataInCode(codeCache.createDataItem(data, 0));
+    }
+
+    public void recordInlineDataInCode(Data data) {
         assert data != null;
         int pos = asm.position();
         Debug.log("Inline data in code: pos = %d, data = %s", pos, data);
@@ -165,7 +168,7 @@
 
     public AbstractAddress recordDataReferenceInCode(Constant data, int alignment) {
         assert data != null;
-        return recordDataReferenceInCode(new ConstantData(data, alignment));
+        return recordDataReferenceInCode(codeCache.createDataItem(data, alignment));
     }
 
     public AbstractAddress recordDataReferenceInCode(Data data) {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Thu Mar 20 13:50:21 2014 +0100
@@ -332,7 +332,7 @@
                     PhiNode phi;
                     switch (vpn.type()) {
                         case Value:
-                            phi = graph.addWithoutUnique(new PhiNode(vpn.getKind(), merge));
+                            phi = graph.addWithoutUnique(new PhiNode(vpn.stamp(), merge));
                             break;
                         case Guard:
                             phi = graph.addWithoutUnique(new PhiNode(vpn.type(), merge));
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Thu Mar 20 13:50:21 2014 +0100
@@ -170,7 +170,7 @@
         PhiNode ret;
         switch (phi.type()) {
             case Value:
-                ret = new PhiNode(phi.getKind(), merge);
+                ret = new PhiNode(phi.stamp(), merge);
                 break;
             case Guard:
                 ret = new PhiNode(PhiType.Guard, merge);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.calc.*;
@@ -53,15 +52,11 @@
     private final PhiType type;
 
     /**
-     * Create a value phi ({@link PhiType#Value}) with the specified kind.
+     * Create a value phi ({@link PhiType#Value}) with the specified stamp.
      * 
-     * @param kind the kind of the value
+     * @param stamp the stamp of the value
      * @param merge the merge that the new phi belongs to
      */
-    public PhiNode(Kind kind, MergeNode merge) {
-        this(StampFactory.forKind(kind), merge);
-    }
-
     public PhiNode(Stamp stamp, MergeNode merge) {
         super(stamp);
         assert stamp != StampFactory.forVoid();
@@ -186,7 +181,7 @@
 
     public void addInput(ValueNode x) {
         assert !(x instanceof PhiNode) || ((PhiNode) x).merge() instanceof LoopBeginNode || ((PhiNode) x).merge() != this.merge();
-        assert x.getKind() == getKind() || type != PhiType.Value;
+        assert x.stamp().isCompatible(stamp()) || type != PhiType.Value;
         values.add(x);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -66,6 +66,14 @@
             if ((rawY & mask) == 0) {
                 return ConstantNode.forIntegerStamp(stamp(), 0, graph());
             }
+            if (x().stamp() instanceof IntegerStamp) {
+                IntegerStamp xStamp = (IntegerStamp) x().stamp();
+                if (((xStamp.upMask() | xStamp.downMask()) & ~rawY) == 0) {
+                    // No bits are set which are outside the mask, so the mask will have no effect.
+                    return x();
+                }
+            }
+
             return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -93,6 +93,10 @@
         if (stamp().isCompatible(value.stamp())) {
             return value;
         }
+        if (value instanceof ReinterpretNode) {
+            ReinterpretNode reinterpret = (ReinterpretNode) value;
+            return value.graph().unique(new ReinterpretNode(stamp(), reinterpret.value()));
+        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -73,7 +73,7 @@
                 return;
             }
         }
-        for (Node usage : usages().snapshot()) {
+        for (Node usage : usages().distinct().snapshot()) {
             List<Node> snapshot = usage.inputs().snapshot();
             graph().removeFixed((FixedWithNextNode) usage);
             for (Node input : snapshot) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java	Thu Mar 20 13:50:21 2014 +0100
@@ -85,8 +85,9 @@
         if (stamp instanceof IllegalStamp) {
             IllegalStamp other = (IllegalStamp) stamp;
             return kind == other.kind;
+        } else {
+            return stamp.isCompatible(this);
         }
-        return false;
     }
 
     @Override
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Thu Mar 20 13:50:21 2014 +0100
@@ -172,7 +172,7 @@
                 String declaringClass = option.declaringClass;
                 Name fieldName = option.field.getSimpleName();
                 String comma = i == info.options.size() - 1 ? "" : ",";
-                out.printf("            new %s(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s)%s%n", desc, name, type, help, declaringClass, fieldName, optionValue, comma);
+                out.printf("            new %s(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s)%s\n", desc, name, type, help, declaringClass, fieldName, optionValue, comma);
                 i++;
             }
             out.println("        );");
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Thu Mar 20 13:50:21 2014 +0100
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -55,8 +56,8 @@
                     if (target instanceof AbstractDeoptimizeNode) {
                         merge = graph.add(new MergeNode());
                         EndNode firstEnd = graph.add(new EndNode());
-                        reasonActionPhi = graph.addWithoutUnique(new PhiNode(Kind.Int, merge));
-                        speculationPhi = graph.addWithoutUnique(new PhiNode(Kind.Object, merge));
+                        reasonActionPhi = graph.addWithoutUnique(new PhiNode(StampFactory.forKind(Kind.Int), merge));
+                        speculationPhi = graph.addWithoutUnique(new PhiNode(StampFactory.forKind(Kind.Object), merge));
                         merge.addForwardEnd(firstEnd);
                         reasonActionPhi.addInput(((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess()));
                         speculationPhi.addInput(((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess()));
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Thu Mar 20 13:50:21 2014 +0100
@@ -91,14 +91,6 @@
         return inliningCount;
     }
 
-    public static void storeStatisticsAfterLowTier(StructuredGraph graph) {
-        ResolvedJavaMethod method = graph.method();
-        if (method != null) {
-            CompiledMethodInfo info = compiledMethodInfo(graph.method());
-            info.setLowLevelNodeCount(graph.getNodeCount());
-        }
-    }
-
     @Override
     protected void run(final StructuredGraph graph, final HighTierContext context) {
         final InliningData data = new InliningData(graph, context.getAssumptions());
@@ -310,15 +302,6 @@
         return newGraph;
     }
 
-    private static synchronized CompiledMethodInfo compiledMethodInfo(ResolvedJavaMethod m) {
-        CompiledMethodInfo info = (CompiledMethodInfo) m.getCompilerStorage().get(CompiledMethodInfo.class);
-        if (info == null) {
-            info = new CompiledMethodInfo();
-            m.getCompilerStorage().put(CompiledMethodInfo.class, info);
-        }
-        return info;
-    }
-
     private abstract static class AbstractInliningPolicy implements InliningPolicy {
 
         protected final Map<Invoke, Double> hints;
@@ -371,7 +354,12 @@
         protected static int previousLowLevelGraphSize(InlineInfo info) {
             int size = 0;
             for (int i = 0; i < info.numberOfMethods(); i++) {
-                size += compiledMethodInfo(info.methodAt(i)).lowLevelNodeCount();
+                ResolvedJavaMethod m = info.methodAt(i);
+                ProfilingInfo profile = m.getProfilingInfo();
+                int compiledGraphSize = profile.getCompilerIRSize(StructuredGraph.class);
+                if (compiledGraphSize > 0) {
+                    size += compiledGraphSize;
+                }
             }
             return size;
         }
@@ -864,21 +852,4 @@
             return (graph != null ? MetaUtil.format("%H.%n(%p)", method()) : "<null method>") + remainingInvokes;
         }
     }
-
-    private static class CompiledMethodInfo {
-
-        private int lowLevelNodes;
-
-        public CompiledMethodInfo() {
-        }
-
-        public int lowLevelNodeCount() {
-            return lowLevelNodes;
-        }
-
-        public void setLowLevelNodeCount(int lowLevelNodes) {
-            this.lowLevelNodes = lowLevelNodes;
-        }
-
-    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Mar 20 13:50:21 2014 +0100
@@ -625,7 +625,7 @@
 
             PhiNode returnValuePhi = null;
             if (invoke.asNode().getKind() != Kind.Void) {
-                returnValuePhi = graph.addWithoutUnique(new PhiNode(invoke.asNode().getKind(), returnMerge));
+                returnValuePhi = graph.addWithoutUnique(new PhiNode(invoke.asNode().stamp().unrestricted(), returnMerge));
             }
 
             MergeNode exceptionMerge = null;
@@ -638,7 +638,7 @@
 
                 FixedNode exceptionSux = exceptionEdge.next();
                 graph.addBeforeFixed(exceptionSux, exceptionMerge);
-                exceptionObjectPhi = graph.addWithoutUnique(new PhiNode(Kind.Object, exceptionMerge));
+                exceptionObjectPhi = graph.addWithoutUnique(new PhiNode(StampFactory.forKind(Kind.Object), exceptionMerge));
                 exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, Kind.Object, exceptionObjectPhi));
             }
 
@@ -1486,7 +1486,7 @@
 
             if (returnNode.result() != null) {
                 if (returnValuePhi == null) {
-                    returnValuePhi = merge.graph().addWithoutUnique(new PhiNode(returnNode.result().getKind(), merge));
+                    returnValuePhi = merge.graph().addWithoutUnique(new PhiNode(returnNode.result().stamp().unrestricted(), merge));
                 }
                 returnValuePhi.addInput(returnNode.result());
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Mar 20 13:50:21 2014 +0100
@@ -312,6 +312,8 @@
                     Mark preLoweringMark = node.graph().getMark();
                     ((Lowerable) node).lower(loweringTool);
                     if (loweringTool.guardAnchor.asNode().isDeleted()) {
+                        // TODO nextNode could be deleted but this is not currently supported
+                        assert nextNode.isAlive();
                         loweringTool.guardAnchor = BeginNode.prevBegin(nextNode);
                     }
                     assert checkPostNodeLowering(node, loweringTool, preLoweringMark, unscheduledUsages);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java	Thu Mar 20 13:50:21 2014 +0100
@@ -87,7 +87,7 @@
         }
         if (lastLocationAccess instanceof PhiNode) {
             PhiNode phi = (PhiNode) lastLocationAccess;
-            PhiNode newPhi = phi.graph().addWithoutUnique(new PhiNode(n.getKind(), phi.merge()));
+            PhiNode newPhi = phi.graph().addWithoutUnique(new PhiNode(n.stamp().unrestricted(), phi.merge()));
             nodeMap.set(phi, newPhi);
             for (ValueNode value : phi.values()) {
                 newPhi.addInput(getValue(n, (MemoryNode) value, nodeMap));
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Thu Mar 20 13:50:21 2014 +0100
@@ -486,7 +486,7 @@
                             // introduce a new phi
                             PhiNode newPhi = bottomPhis.get(node);
                             if (newPhi == null) {
-                                newPhi = graph.addWithoutUnique(new PhiNode(node.getKind(), newBottomMerge));
+                                newPhi = graph.addWithoutUnique(new PhiNode(node.stamp().unrestricted(), newBottomMerge));
                                 bottomPhis.put(node, newPhi);
                                 newPhi.addInput(node);
                             }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Thu Mar 20 13:50:21 2014 +0100
@@ -36,7 +36,7 @@
  */
 public abstract class BasePhase<C> {
 
-    private final String name;
+    private CharSequence name;
 
     private final DebugTimer phaseTimer;
     private final DebugMetric phaseMetric;
@@ -49,25 +49,18 @@
     }
 
     protected BasePhase() {
-        String nm = this.getClass().getSimpleName();
-        if (nm.endsWith("Phase")) {
-            name = nm.substring(0, nm.length() - "Phase".length());
-        } else {
-            name = nm;
-        }
-        assert checkName(name);
-        phaseTimer = Debug.timer("PhaseTime_" + name);
-        phaseMetric = Debug.metric("PhaseCount_" + name);
+        phaseTimer = Debug.timer("PhaseTime_%s", getClass());
+        phaseMetric = Debug.metric("PhaseCount_%s", getClass());
     }
 
     protected BasePhase(String name) {
         assert checkName(name);
         this.name = name;
-        phaseTimer = Debug.timer("PhaseTime_" + name);
-        phaseMetric = Debug.metric("PhaseCount_" + name);
+        phaseTimer = Debug.timer("PhaseTime_%s", getClass());
+        phaseMetric = Debug.metric("PhaseCount_%s", getClass());
     }
 
-    protected String getDetailedName() {
+    protected CharSequence getDetailedName() {
         return getName();
     }
 
@@ -76,7 +69,7 @@
     }
 
     public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) {
-        try (TimerCloseable a = phaseTimer.start(); Scope s = Debug.scope(name, this)) {
+        try (TimerCloseable a = phaseTimer.start(); Scope s = Debug.scope(getClass(), this)) {
             BasePhase.this.run(graph, context);
             phaseMetric.increment();
             if (dumpGraph) {
@@ -88,7 +81,14 @@
         }
     }
 
-    public final String getName() {
+    public final CharSequence getName() {
+        if (name == null) {
+            String s = BasePhase.this.getClass().getSimpleName();
+            if (s.endsWith("Phase")) {
+                s = s.substring(0, s.length() - "Phase".length());
+            }
+            name = s;
+        }
         return name;
     }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Thu Mar 20 13:50:21 2014 +0100
@@ -177,6 +177,8 @@
     @Option(help = "")
     public static final OptionValue<Boolean> HotSpotPrintCompilation = new OptionValue<>(false);
     @Option(help = "")
+    public static final OptionValue<Boolean> HotSpotCIPrintCompilerName = new OptionValue<>(false);
+    @Option(help = "")
     public static final OptionValue<Boolean> HotSpotPrintInlining = new OptionValue<>(false);
 
     // Register allocator debugging
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/LazyName.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, 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.phases;
+
+import com.oracle.graal.debug.*;
+
+/**
+ * A name whose {@link String} value is computed only when it is needed. This is useful in
+ * combination with debugging facilities such as {@link Debug#scope(Object)} where the
+ * {@link String} value of a name is only needed if debugging is enabled.
+ */
+public abstract class LazyName implements CharSequence {
+
+    private String value;
+
+    public int length() {
+        return toString().length();
+    }
+
+    public char charAt(int index) {
+        return toString().charAt(index);
+    }
+
+    public CharSequence subSequence(int start, int end) {
+        return toString().subSequence(start, end);
+    }
+
+    @Override
+    public final String toString() {
+        if (value == null) {
+            value = createString();
+        }
+        return value;
+    }
+
+    /**
+     * Creates the {@link String} value of this name.
+     */
+    protected abstract String createString();
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Thu Mar 20 13:50:21 2014 +0100
@@ -85,7 +85,7 @@
 
     private static void visitForward(ArrayList<Node> nodes, NodeBitMap visited, Node node, boolean floatingOnly) {
         try {
-            assert node.isAlive() : node + " not alive";
+            assert node == null || node.isAlive() : node + " not alive";
             if (node != null && !visited.isMarked(node)) {
                 if (floatingOnly && node instanceof FixedNode) {
                     throw new GraalInternalError("unexpected reference to fixed node: %s (this indicates an unexpected cycle)", node);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/MethodDebugValueName.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, 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.phases.util;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * Lazily computed debug value name composed of a prefix and a {@linkplain JavaMethod#getName()
+ * method name}.
+ */
+public class MethodDebugValueName extends LazyName {
+    final String prefix;
+    final JavaMethod method;
+
+    public MethodDebugValueName(String prefix, JavaMethod method) {
+        this.prefix = prefix;
+        this.method = method;
+    }
+
+    @Override
+    public String createString() {
+        return prefix + "[" + method.getName() + "]";
+    }
+}
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Thu Mar 20 13:50:21 2014 +0100
@@ -41,6 +41,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.phases.schedule.*;
 
 /**
  * Utility for printing Graal IR at various compilation phases.
@@ -51,6 +52,7 @@
     protected LIR lir;
     protected LIRGenerator lirGenerator;
     protected ControlFlowGraph cfg;
+    protected SchedulePhase schedule;
 
     /**
      * Creates a control flow graph printer.
@@ -118,7 +120,7 @@
     private NodeBitMap printedNodes;
 
     private boolean inFixedSchedule(Node node) {
-        return lir != null || node.isDeleted() || cfg.getNodeToBlock().get(node) != null;
+        return lir != null || schedule != null || node.isDeleted() || cfg.getNodeToBlock().get(node) != null;
     }
 
     /**
@@ -185,6 +187,20 @@
     }
 
     private void printBlock(AbstractBlock<?> block, boolean printNodes) {
+        printBlockProlog(block);
+        if (printNodes) {
+            assert block instanceof Block;
+            printNodes((Block) block);
+        }
+        printBlockEpilog(block);
+    }
+
+    private void printBlockEpilog(AbstractBlock<?> block) {
+        printLIR(block);
+        end("block");
+    }
+
+    private void printBlockProlog(AbstractBlock<?> block) {
         begin("block");
 
         out.print("name \"").print(blockToString(block)).println('"');
@@ -229,18 +245,10 @@
             out.print("loop_index ").println(block.getLoop().index);
             out.print("loop_depth ").println(block.getLoop().depth);
         }
-
-        if (printNodes) {
-            printedNodes = new NodeBitMap(cfg.graph);
-            assert block instanceof Block;
-            printNodes((Block) block);
-            printedNodes = null;
-        }
-        printLIR(block);
-        end("block");
     }
 
     private void printNodes(Block block) {
+        printedNodes = new NodeBitMap(cfg.graph);
         begin("IR");
         out.println("HIR");
         out.disableIndentation();
@@ -274,6 +282,7 @@
 
         out.enableIndentation();
         end("IR");
+        printedNodes = null;
     }
 
     private void printNode(Node node, boolean unscheduled) {
@@ -289,7 +298,7 @@
         }
 
         if (unscheduled) {
-            assert lir == null : "unscheduled nodes can only be present before LIR generation";
+            assert lir == null && schedule == null : "unscheduled nodes can only be present before LIR generation";
             out.print("f ").print(HOVER_START).print("u").print(HOVER_SEP).print("unscheduled").print(HOVER_END).println(COLUMN_END);
         } else if (node instanceof FixedWithNextNode) {
             out.print("f ").print(HOVER_START).print("#").print(HOVER_SEP).print("fixed with next").print(HOVER_END).println(COLUMN_END);
@@ -466,7 +475,7 @@
             return "-";
         }
         String prefix;
-        if (node instanceof AbstractBeginNode && lir == null) {
+        if (node instanceof AbstractBeginNode && (lir == null && schedule == null)) {
             prefix = "B";
         } else if (node instanceof ValueNode) {
             ValueNode value = (ValueNode) node;
@@ -482,7 +491,7 @@
     }
 
     private String blockToString(AbstractBlock<?> block) {
-        if (lir == null && block instanceof Block) {
+        if (lir == null && schedule == null && block instanceof Block) {
             // During all the front-end phases, the block schedule is built only for the debug
             // output.
             // Therefore, the block numbers would be different for every CFG printed -> use the id
@@ -541,4 +550,46 @@
         out.printf(" \"%s\"", interval.spillState());
         out.println();
     }
+
+    public void printSchedule(String message, SchedulePhase theSchedule) {
+        schedule = theSchedule;
+        cfg = schedule.getCFG();
+        printedNodes = new NodeBitMap(cfg.graph);
+
+        begin("cfg");
+        out.print("name \"").print(message).println('"');
+        for (Block b : schedule.getCFG().getBlocks()) {
+            if (schedule.nodesFor(b) != null) {
+                printScheduledBlock(b, schedule.nodesFor(b));
+            }
+        }
+        end("cfg");
+
+        schedule = null;
+        cfg = null;
+        printedNodes = null;
+    }
+
+    private void printScheduledBlock(Block block, List<ScheduledNode> nodesFor) {
+        printBlockProlog(block);
+        begin("IR");
+        out.println("HIR");
+        out.disableIndentation();
+
+        if (block.getBeginNode() instanceof MergeNode) {
+            // Currently phi functions are not in the schedule, so print them separately here.
+            for (ValueNode phi : ((MergeNode) block.getBeginNode()).phis()) {
+                printNode(phi, false);
+            }
+        }
+
+        for (Node n : nodesFor) {
+            printNode(n, false);
+        }
+
+        out.enableIndentation();
+        end("IR");
+
+        printBlockEpilog(block);
+    }
 }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Mar 20 13:50:21 2014 +0100
@@ -36,6 +36,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.phases.schedule.*;
 
 /**
  * Observes compilation events and uses {@link CFGPrinter} to produce a control flow graph for the
@@ -162,6 +163,8 @@
             boolean printNodes = previousObject != object && cfgPrinter.cfg != null;
             cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder(), printNodes);
 
+        } else if (object instanceof SchedulePhase) {
+            cfgPrinter.printSchedule(message, (SchedulePhase) object);
         } else if (object instanceof StructuredGraph) {
             if (cfgPrinter.cfg == null) {
                 StructuredGraph graph = (StructuredGraph) object;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Thu Mar 20 13:50:21 2014 +0100
@@ -134,16 +134,17 @@
      */
     protected String debugInfoToString(BytecodePosition codePos, ReferenceMap refMap, RegisterSaveLayout calleeSaveInfo, Architecture arch) {
         StringBuilder sb = new StringBuilder();
+        RefMapFormatter formatter = new CodeUtil.NumberedRefMapFormatter();
 
         if (refMap != null && refMap.hasRegisterRefMap()) {
             sb.append("reg-ref-map:");
-            refMap.appendRegisterMap(sb, arch != null ? new ArchitectureRegFormatter(arch) : null);
+            refMap.appendRegisterMap(sb, arch != null ? new ArchitectureRegFormatter(arch) : formatter);
             sb.append("\n");
         }
 
         if (refMap != null && refMap.hasFrameRefMap()) {
             sb.append("frame-ref-map:");
-            refMap.appendFrameMap(sb, null);
+            refMap.appendFrameMap(sb, formatter);
             sb.append("\n");
         }
 
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java	Thu Mar 20 13:50:21 2014 +0100
@@ -35,6 +35,7 @@
 
 public class DecompilerDebugDumpHandler implements DebugDumpHandler {
 
+    public static boolean printToNowhere;
     private final PrintStream infoPrintStream = System.out;
     private File file;
     private FileOutputStream fos;
@@ -55,6 +56,15 @@
                 filter = filter.substring(0, filter.indexOf("Phase"));
             }
 
+            if (printToNowhere) {
+                printStream = new PrintStream(new OutputStream() {
+                    @Override
+                    public void write(int b) throws IOException {
+                        // DO NOTHING
+                    }
+                });
+            }
+
             if (printStream == null) {
                 fileName = "decompilerDump_" + uniqueId.incrementAndGet() + "_" + System.currentTimeMillis() + ".txt";
                 file = new File(fileName);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Thu Mar 20 13:50:21 2014 +0100
@@ -202,7 +202,7 @@
         for (Object o : Debug.context()) {
             JavaMethod method = asJavaMethod(o);
             if (method != null) {
-                if (lastMethodOrGraph == null || !asJavaMethod(lastMethodOrGraph).equals(method)) {
+                if (lastMethodOrGraph == null || asJavaMethod(lastMethodOrGraph) == null || !asJavaMethod(lastMethodOrGraph).equals(method)) {
                     result.add(MetaUtil.format("%H::%n(%p)", method));
                 } else {
                     // This prevents multiple adjacent method context objects for the same method
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java	Thu Mar 20 13:50:21 2014 +0100
@@ -293,9 +293,8 @@
         }
 
         void warning(int offset, String message) {
-            // CheckStyle: stop system..print check
-            System.err.println("Warning: " + errorMessage(offset, message));
-            // CheckStyle: resume system..print check
+            PrintStream err = System.err;
+            err.println("Warning: " + errorMessage(offset, message));
         }
 
         String errorMessage(int offset, String message) {
@@ -323,10 +322,9 @@
             int lineStart = input.lastIndexOf(HexCodeFile.NEW_LINE, index) + 1;
 
             String l = input.substring(lineStart, lineStart + 10);
-            // CheckStyle: stop system..print check
-            System.out.println("YYY" + input.substring(index, index + 10) + "...");
-            System.out.println("XXX" + l + "...");
-            // CheckStyle: resume system..print check
+            PrintStream out = System.out;
+            out.println("YYY" + input.substring(index, index + 10) + "...");
+            out.println("XXX" + l + "...");
 
             int pos = input.indexOf(HexCodeFile.NEW_LINE, 0);
             int line = 1;
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -29,8 +29,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.virtual.phases.ea.*;
 
 /**
  * Tests {@link ArraysSubstitutions}.
@@ -329,4 +333,111 @@
         return Arrays.equals(a, b);
     }
 
+    @Test
+    public void testEqualsNodeGVN() {
+        test("testEqualsNodeGVNSnippet", true);
+    }
+
+    public static int[] intArrayCompare = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
+    public static int[] intArray;
+
+    public static boolean testEqualsNodeGVNSnippet(boolean b) {
+        int[] newIntArray = new int[]{0, 2, 3, 4, 5, 6, 7, 8, 9};
+        intArray = newIntArray;
+
+        if (b) {
+            newIntArray[0] = 1;
+            return Arrays.equals(newIntArray, intArrayCompare);
+        } else {
+            newIntArray[0] = 1;
+            return Arrays.equals(newIntArray, intArrayCompare);
+        }
+    }
+
+    @Test
+    public void testConstants() {
+        test("testConstantsSnippet");
+    }
+
+    public static final int[] constantArray1 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
+    public static final int[] constantArray2 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+    public static boolean testConstantsSnippet() {
+        constantArray2[0] = 10;
+        try {
+            return Arrays.equals(constantArray1, constantArray2);
+        } finally {
+            constantArray2[0] = 1;
+        }
+    }
+
+    @Test
+    public void testCanonicalLength() {
+        StructuredGraph graph = parse("testCanonicalLengthSnippet");
+        Assumptions assumptions = new Assumptions(false);
+        HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
+
+        Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 0);
+    }
+
+    public static final int[] constantArray3 = new int[]{1, 2, 3};
+
+    public static boolean testCanonicalLengthSnippet() {
+        return Arrays.equals(constantArray1, constantArray3);
+    }
+
+    @Test
+    public void testCanonicalEqual() {
+        StructuredGraph graph = parse("testCanonicalEqualSnippet");
+        Assumptions assumptions = new Assumptions(false);
+        HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
+
+        Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 1);
+    }
+
+    public static boolean testCanonicalEqualSnippet() {
+        return Arrays.equals(constantArray1, constantArray1);
+    }
+
+    @Test
+    public void testVirtualEqual() {
+        StructuredGraph graph = parse("testVirtualEqualSnippet");
+        Assumptions assumptions = new Assumptions(false);
+        HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
+        new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
+
+        Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 1);
+    }
+
+    public static boolean testVirtualEqualSnippet() {
+        int[] array1 = new int[]{1, 2, 3, 4};
+        int[] array2 = new int[]{1, 2, 3, 4};
+        return Arrays.equals(array1, array2);
+    }
+
+    @Test
+    public void testVirtualNotEqual() {
+        StructuredGraph graph = parse("testVirtualNotEqualSnippet");
+        Assumptions assumptions = new Assumptions(false);
+        HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
+        new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
+
+        Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 0);
+    }
+
+    public static boolean testVirtualNotEqualSnippet(int x) {
+        int[] array1 = new int[]{1, 2, 100, x};
+        int[] array2 = new int[]{1, 2, 3, 4};
+        return Arrays.equals(array1, array2);
+    }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Thu Mar 20 13:50:21 2014 +0100
@@ -99,7 +99,7 @@
                 FrameStateProcessing frameStateProcessing = method.getAnnotation(Snippet.class).removeAllFrameStates() ? FrameStateProcessing.Removal
                                 : FrameStateProcessing.CollapseFrameForSingleSideEffect;
                 StructuredGraph newGraph = makeGraph(method, recursiveEntry, recursiveEntry, inliningPolicy(method), frameStateProcessing);
-                Debug.metric("SnippetNodeCount[" + method.getName() + "]").add(newGraph.getNodeCount());
+                Debug.metric("SnippetNodeCount[%#s]", method).add(newGraph.getNodeCount());
                 if (!UseSnippetGraphCache) {
                     return newGraph;
                 }
@@ -201,8 +201,8 @@
                     }
                 }
             }
-            // We don't have per method guards for macro substitutions but at least respect the
-            // defaultGuard if there is one.
+            // We don't have per method guards for macro substitutions but at
+            // least respect the defaultGuard if there is one.
             if (macroSubstitution != null && (defaultGuard == null || defaultGuard.execute())) {
                 String originalName = originalName(substituteMethod, macroSubstitution.value());
                 JavaSignature originalSignature = originalSignature(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic());
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Thu Mar 20 13:50:21 2014 +0100
@@ -24,6 +24,8 @@
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.debug.Debug.*;
+import static java.util.FormattableFlags.*;
 
 import java.io.*;
 import java.lang.reflect.*;
@@ -97,8 +99,8 @@
 
         protected SnippetInfo(ResolvedJavaMethod method) {
             this.method = method;
-            instantiationCounter = Debug.metric("SnippetInstantiationCount[" + method.getName() + "]");
-            instantiationTimer = Debug.timer("SnippetInstantiationTime[" + method.getName() + "]");
+            instantiationCounter = Debug.metric("SnippetInstantiationCount[%#s]", method);
+            instantiationTimer = Debug.timer("SnippetInstantiationTime[%#s]", method);
             assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method);
             int count = method.getSignature().getParameterCount(false);
             constantParameters = new boolean[count];
@@ -176,7 +178,7 @@
      * {@link SnippetTemplate#instantiate instantiated}
      * </ul>
      */
-    public static class Arguments {
+    public static class Arguments implements Formattable {
 
         protected final SnippetInfo info;
         protected final CacheKey cacheKey;
@@ -243,6 +245,30 @@
             result.append(">");
             return result.toString();
         }
+
+        public void formatTo(Formatter formatter, int flags, int width, int precision) {
+            if ((flags & ALTERNATE) == 0) {
+                formatter.format(applyFormattingFlagsAndWidth(toString(), flags, width));
+            } else {
+                StringBuilder sb = new StringBuilder();
+                sb.append(info.method.getName()).append('(');
+                String sep = "";
+                for (int i = 0; i < info.getParameterCount(); i++) {
+                    if (info.isConstantParameter(i)) {
+                        sb.append(sep);
+                        if (info.names[i] != null) {
+                            sb.append(info.names[i]);
+                        } else {
+                            sb.append(i);
+                        }
+                        sb.append('=').append(values[i]);
+                        sep = ", ";
+                    }
+                }
+                sb.append(")");
+                formatter.format(applyFormattingFlagsAndWidth(sb.toString(), flags & ~ALTERNATE, width));
+            }
+        }
     }
 
     /**
@@ -440,38 +466,13 @@
         return false;
     }
 
-    private static String debugValueName(String category, Arguments args) {
-        if (Debug.isEnabled()) {
-            StringBuilder result = new StringBuilder(category).append('[');
-            SnippetInfo info = args.info;
-            result.append(info.method.getName()).append('(');
-            String sep = "";
-            for (int i = 0; i < info.getParameterCount(); i++) {
-                if (info.isConstantParameter(i)) {
-                    result.append(sep);
-                    if (info.names[i] != null) {
-                        result.append(info.names[i]);
-                    } else {
-                        result.append(i);
-                    }
-                    result.append('=').append(args.values[i]);
-                    sep = ", ";
-                }
-            }
-            result.append(")]");
-            return result.toString();
-
-        }
-        return null;
-    }
-
     /**
      * Creates a snippet template.
      */
     protected SnippetTemplate(final Providers providers, Arguments args) {
         StructuredGraph snippetGraph = providers.getReplacements().getSnippet(args.info.method);
-        instantiationTimer = Debug.timer(debugValueName("SnippetTemplateInstantiationTime", args));
-        instantiationCounter = Debug.metric(debugValueName("SnippetTemplateInstantiationCount", args));
+        instantiationTimer = Debug.timer("SnippetTemplateInstantiationTime[%#s]", args);
+        instantiationCounter = Debug.metric("SnippetTemplateInstantiationCount[%#s]", args);
 
         ResolvedJavaMethod method = snippetGraph.method();
         Signature signature = method.getSignature();
@@ -665,7 +666,7 @@
             }
         }
 
-        Debug.metric(debugValueName("SnippetTemplateNodeCount", args)).add(nodes.size());
+        Debug.metric("SnippetTemplateNodeCount[%#s]", args).add(nodes.size());
         args.info.notifyNewTemplate();
         Debug.dump(snippet, "SnippetTemplate final state");
     }
@@ -876,10 +877,11 @@
 
         @Override
         public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) {
-            if (mmap != null && newNode != null) {
+            if (mmap != null) {
                 for (Node usage : oldNode.usages().snapshot()) {
                     LocationIdentity identity = getLocationIdentity(usage);
-                    if (identity != null && identity != LocationIdentity.FINAL_LOCATION) {
+                    boolean usageReplaced = false;
+                    if (identity != null && identity != FINAL_LOCATION) {
                         // lastLocationAccess points into the snippet graph. find a proper
                         // MemoryCheckPoint inside the snippet graph
                         MemoryNode lastAccess = mmap.getLastLocationAccess(identity);
@@ -888,17 +890,26 @@
                         if (usage instanceof MemoryAccess) {
                             MemoryAccess access = (MemoryAccess) usage;
                             if (access.getLastLocationAccess() == oldNode) {
-                                assert newNode.graph().isAfterFloatingReadPhase();
+                                assert oldNode.graph().isAfterFloatingReadPhase();
                                 access.setLastLocationAccess(lastAccess);
+                                usageReplaced = true;
                             }
                         } else {
                             assert usage instanceof MemoryProxy || usage instanceof MemoryPhiNode;
                             usage.replaceFirstInput(oldNode, lastAccess.asNode());
+                            usageReplaced = true;
                         }
                     }
+                    if (!usageReplaced) {
+                        assert newNode != null : "this branch is only valid if we have a newNode for replacement";
+                    }
                 }
             }
-            oldNode.replaceAtUsages(newNode);
+            if (newNode == null) {
+                assert oldNode.usages().isEmpty();
+            } else {
+                oldNode.replaceAtUsages(newNode);
+            }
         }
     };
 
@@ -1002,12 +1013,6 @@
             // Re-wire the control flow graph around the replacee
             FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
             replacee.replaceAtPredecessor(firstCFGNodeDuplicate);
-            FixedNode next = null;
-            if (replacee instanceof FixedWithNextNode) {
-                FixedWithNextNode fwn = (FixedWithNextNode) replacee;
-                next = fwn.next();
-                fwn.setNext(null);
-            }
 
             if (replacee instanceof StateSplit) {
                 for (StateSplit sideEffectNode : sideEffectNodes) {
@@ -1036,12 +1041,18 @@
                 returnValue = returnDuplicate.result();
                 MemoryMapNode mmap = new DuplicateMapper(duplicates, replaceeGraph.start());
                 if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) {
-                    replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor(), mmap);
+                    replacer.replace(replacee, null, mmap);
                 } else {
                     assert returnValue != null || replacee.usages().isEmpty();
                     replacer.replace(replacee, returnValue, mmap);
                 }
                 if (returnDuplicate.isAlive()) {
+                    FixedNode next = null;
+                    if (replacee instanceof FixedWithNextNode) {
+                        FixedWithNextNode fwn = (FixedWithNextNode) replacee;
+                        next = fwn.next();
+                        fwn.setNext(null);
+                    }
                     returnDuplicate.clearInputs();
                     returnDuplicate.replaceAndDelete(next);
                 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.replacements.nodes;
 
-import java.util.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
@@ -31,13 +29,14 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 /**
  * Compares two arrays with the same length.
  */
-public class ArrayEqualsNode extends FloatingNode implements LIRGenLowerable, Canonicalizable {
+public class ArrayEqualsNode extends FixedWithNextNode implements LIRGenLowerable, Canonicalizable, Virtualizable {
 
     /** {@link Kind} of the arrays to compare. */
     private final Kind kind;
@@ -66,42 +65,45 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (!array1.isConstant() || !array2.isConstant()) {
-            return this;
+        if (usages().isEmpty()) {
+            return null;
         }
+        if (GraphUtil.unproxify(array1) == GraphUtil.unproxify(array2)) {
+            return ConstantNode.forBoolean(true, graph());
+        }
+        return this;
+    }
 
-        Object a1 = array1.asConstant().asObject();
-        Object a2 = array2.asConstant().asObject();
-        boolean x;
-        switch (kind) {
-            case Boolean:
-                x = Arrays.equals((boolean[]) a1, (boolean[]) a2);
-                break;
-            case Byte:
-                x = Arrays.equals((byte[]) a1, (byte[]) a2);
-                break;
-            case Char:
-                x = Arrays.equals((char[]) a1, (char[]) a2);
-                break;
-            case Short:
-                x = Arrays.equals((short[]) a1, (short[]) a2);
-                break;
-            case Int:
-                x = Arrays.equals((int[]) a1, (int[]) a2);
-                break;
-            case Long:
-                x = Arrays.equals((long[]) a1, (long[]) a2);
-                break;
-            case Float:
-                x = Arrays.equals((float[]) a1, (float[]) a2);
-                break;
-            case Double:
-                x = Arrays.equals((double[]) a1, (double[]) a2);
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere("unknown kind " + kind);
+    public void virtualize(VirtualizerTool tool) {
+        State state1 = tool.getObjectState(array1);
+        if (state1 != null) {
+            State state2 = tool.getObjectState(array2);
+            if (state2 != null) {
+                if (state1.getVirtualObject() == state2.getVirtualObject()) {
+                    // the same virtual objects will always have the same contents
+                    tool.replaceWithValue(ConstantNode.forBoolean(true, graph()));
+                } else if (state1.getVirtualObject().entryCount() == state2.getVirtualObject().entryCount()) {
+                    int entryCount = state1.getVirtualObject().entryCount();
+                    boolean allEqual = true;
+                    for (int i = 0; i < entryCount; i++) {
+                        ValueNode entry1 = state1.getEntry(i);
+                        ValueNode entry2 = state2.getEntry(i);
+                        if (entry1 != entry2) {
+                            // the contents might be different
+                            allEqual = false;
+                        }
+                        if (entry1.stamp().alwaysDistinct(entry2.stamp())) {
+                            // the contents are different
+                            tool.replaceWithValue(ConstantNode.forBoolean(false, graph()));
+                            return;
+                        }
+                    }
+                    if (allEqual) {
+                        tool.replaceWithValue(ConstantNode.forBoolean(true, graph()));
+                    }
+                }
+            }
         }
-        return ConstantNode.forBoolean(x, graph());
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Thu Mar 20 13:50:21 2014 +0100
@@ -162,7 +162,6 @@
                 case Int:
                 case Long:
                 case Object:
-                case NarrowOop:
                     return true;
             }
         } else if (category == FPU) {
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java	Thu Mar 20 13:50:21 2014 +0100
@@ -29,8 +29,8 @@
 import com.oracle.graal.asm.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.truffle.*;
@@ -51,10 +51,9 @@
     @Override
     public Mark recordMark(Object id) {
         Mark mark = super.recordMark(id);
-        if (Integer.valueOf(Marks.MARK_VERIFIED_ENTRY).equals(id)) {
-            HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig();
+        if (MarkId.getEnum((int) id) == MarkId.VERIFIED_ENTRY) {
             HotSpotRegistersProvider registers = HotSpotGraalRuntime.runtime().getHostProviders().getRegisters();
-            injectTailCallCode(config, registers);
+            injectTailCallCode(HotSpotGraalRuntime.runtime().getConfig(), registers);
         }
         return mark;
     }
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ControlFlowExceptionPartialEvaluationTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ControlFlowExceptionPartialEvaluationTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -62,7 +62,7 @@
         @Child private AbstractTestNode child;
 
         public CatchControlFlowExceptionTestNode(AbstractTestNode child) {
-            this.child = adoptChild(child);
+            this.child = child;
         }
 
         @Override
@@ -80,7 +80,7 @@
         @Child private AbstractTestNode child;
 
         public CatchSlowPathAndControlFlowExceptionTestNode(AbstractTestNode child) {
-            this.child = adoptChild(child);
+            this.child = child;
         }
 
         @Override
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -30,8 +30,8 @@
     @Child private AbstractTestNode right;
 
     public AddTestNode(AbstractTestNode left, AbstractTestNode right) {
-        this.left = adoptChild(left);
-        this.right = adoptChild(right);
+        this.left = left;
+        this.right = right;
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -30,7 +30,7 @@
     @Children private final AbstractTestNode[] statements;
 
     public BlockTestNode(AbstractTestNode[] statements) {
-        this.statements = adoptChildren(statements);
+        this.statements = statements;
     }
 
     @ExplodeLoop
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -31,7 +31,7 @@
 
     public LoopTestNode(int numberOfIterations, AbstractTestNode child) {
         this.numberOfIterations = numberOfIterations;
-        this.child = adoptChild(child);
+        this.child = child;
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -22,13 +22,13 @@
  */
 package com.oracle.graal.truffle;
 
-import java.util.concurrent.atomic.*;
+import java.util.*;
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter;
 
 /**
  * Call target that is optimized by Graal upon surpassing a specific invocation threshold.
@@ -60,7 +60,7 @@
     }
 
     @SuppressWarnings("unused")
-    public void nodeReplaced(Node oldNode, Node newNode, String reason) {
+    public void nodeReplaced(Node oldNode, Node newNode, CharSequence reason) {
     }
 
     @Override
@@ -85,6 +85,11 @@
         return new DefaultOptimizedCallNode(target);
     }
 
+    @Override
+    public boolean isInlinable() {
+        return true;
+    }
+
     private static final class DefaultOptimizedCallNode extends OptimizedCallNode {
 
         private boolean trySplit = true;
@@ -120,54 +125,49 @@
             if (!isSplittable()) {
                 return false;
             }
-            int nodeCount = NodeUtil.countNodes(getCallTarget().getRootNode(), null, false);
+            int nodeCount = NodeUtil.countNodes(getCallTarget().getRootNode(), OptimizedCallNodeProfile.COUNT_FILTER, false);
             if (nodeCount > TruffleCompilerOptions.TruffleSplittingMaxCalleeSize.getValue()) {
                 return false;
             }
 
-            // // is the only call target -> do not split
-            // if (getCallTarget().getRootNode().getCachedCallNodes().size() == 1 &&
-            // getCallTarget().getRootNode().getCachedCallNodes().contains(this)) {
-            // return false;
-            // }
+            // disable recursive splitting for now
+            OptimizedCallTarget splitTarget = getCallTarget();
+            List<OptimizedCallTarget> compilationRoots = OptimizedCallNodeProfile.findCompilationRoots(this);
+            for (OptimizedCallTarget compilationRoot : compilationRoots) {
+                if (compilationRoot == splitTarget || compilationRoot.getSplitSource() == splitTarget) {
+                    // recursive call found
+                    return false;
+                }
+            }
 
             // max one child call and callCount > 2 and kind of small number of nodes
             if (isMaxSingleCall()) {
                 return true;
             }
-            return countPolymorphic() >= 1 || countGeneric() > 0;
+            return countPolymorphic() >= 1;
         }
 
         @Override
-        public void nodeReplaced(Node oldNode, Node newNode, String reason) {
-            trySplit = true;
-        }
-
-        @Override
-        protected void notifyCallNodeAdded() {
+        public void nodeReplaced(Node oldNode, Node newNode, CharSequence reason) {
             trySplit = true;
         }
 
         private boolean isMaxSingleCall() {
-            final AtomicInteger count = new AtomicInteger(0);
-            getCurrentCallTarget().getRootNode().accept(new NodeVisitor() {
-
-                public boolean visit(Node node) {
-                    if (node instanceof CallNode) {
-                        return count.incrementAndGet() > 1;
-                    }
-                    return true;
+            return NodeUtil.countNodes(getCurrentCallTarget().getRootNode(), new NodeCountFilter() {
+                public boolean isCounted(Node node) {
+                    return node instanceof CallNode;
                 }
-            });
-            return count.get() <= 1;
+            }) <= 1;
         }
 
         private int countPolymorphic() {
-            return NodeUtil.countNodes(getCallTarget().getRootNode(), null, Kind.POLYMORPHIC, false);
-        }
-
-        private int countGeneric() {
-            return NodeUtil.countNodes(getCallTarget().getRootNode(), null, Kind.GENERIC, false);
+            return NodeUtil.countNodes(getCallTarget().getRootNode(), new NodeCountFilter() {
+                public boolean isCounted(Node node) {
+                    NodeCost cost = node.getCost();
+                    boolean polymorphic = cost == NodeCost.POLYMORPHIC || cost == NodeCost.MEGAMORPHIC;
+                    return polymorphic;
+                }
+            });
         }
 
         @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNodeProfile.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNodeProfile.java	Thu Mar 20 13:50:21 2014 +0100
@@ -27,11 +27,13 @@
 import java.util.*;
 
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeUtil.*;
 
 public class OptimizedCallNodeProfile implements TruffleInliningProfile {
 
+    static final CountFilter COUNT_FILTER = new CountFilter();
+
     private static final String REASON_RECURSION = "recursion";
-    private static final String REASON_FREQUENCY_CUTOFF = "frequency < " + TruffleInliningMinFrequency.getValue();
     private static final String REASON_MAXIMUM_NODE_COUNT = "shallowTargetCount  > " + TruffleInliningMaxCalleeSize.getValue();
     private static final String REASON_MAXIMUM_TOTAL_NODE_COUNT = "inlinedTotalCount > " + TruffleInliningMaxCallerSize.getValue();
 
@@ -49,8 +51,8 @@
         this.callNode = callNode;
         RootNode inlineRoot = callNode.getCurrentCallTarget().getRootNode();
         this.callTarget = target;
-        this.targetShallowNodeCount = NodeUtil.countNodes(inlineRoot, null, false);
-        this.targetDeepNodeCount = NodeUtil.countNodes(inlineRoot, null, true);
+        this.targetShallowNodeCount = NodeUtil.countNodes(inlineRoot, COUNT_FILTER, false);
+        this.targetDeepNodeCount = NodeUtil.countNodes(inlineRoot, COUNT_FILTER, true);
         this.compilationRoots = findCompilationRoots(callNode);
         this.averageFrequency = calculateFrequency();
         this.score = calculateScore();
@@ -84,18 +86,12 @@
             }
         }
 
-        // frequency cut-off
-        if (averageFrequency < TruffleInliningMinFrequency.getValue() && targetDeepNodeCount > TruffleInliningTrivialSize.getValue()) {
-            reason = REASON_FREQUENCY_CUTOFF;
-            return false;
-        }
-
         if (targetShallowNodeCount > TruffleInliningMaxCalleeSize.getValue()) {
             reason = REASON_MAXIMUM_NODE_COUNT;
             return false;
         }
 
-        this.targetDeepNodeCount = NodeUtil.countNodes(inlineTarget.getRootNode(), null, true);
+        this.targetDeepNodeCount = NodeUtil.countNodes(inlineTarget.getRootNode(), COUNT_FILTER, true);
         // The maximum total node count cannot be cached since it may change during inlining.
         int nextNodeCount = calculateInlinedTotalNodeCount(getCallNode());
         if (nextNodeCount > TruffleInliningMaxCallerSize.getValue()) {
@@ -116,6 +112,20 @@
         return currentNodeCount;
     }
 
+    static class CountFilter implements NodeCountFilter {
+        public boolean isCounted(Node node) {
+            return countNode(node) >= 1;
+        }
+    }
+
+    static int countNode(Node node) {
+        NodeCost cost = node.getCost();
+        if (cost != null && cost != NodeCost.NONE && cost != NodeCost.UNINITIALIZED) {
+            return 1;
+        }
+        return 0;
+    }
+
     private static class TotalNodeCountVisitor implements NodeVisitor {
 
         private final OptimizedCallNode inlinedNode;
@@ -129,7 +139,7 @@
         }
 
         public boolean visit(Node node) {
-            count++;
+            count += countNode(node);
             if (node instanceof OptimizedCallNode) {
                 OptimizedCallNode callNode = ((OptimizedCallNode) node);
                 if (callNode == inlinedNode) {
@@ -191,7 +201,7 @@
         return callNode.getCallCount() / (double) callTarget.getCompilationProfile().getCallCount();
     }
 
-    private static List<OptimizedCallTarget> findCompilationRoots(Node call) {
+    static List<OptimizedCallTarget> findCompilationRoots(Node call) {
         RootNode root = call.getRootNode();
         if (root == null) {
             return Collections.emptyList();
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Thu Mar 20 13:50:21 2014 +0100
@@ -34,7 +34,7 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter;
 
 /**
  * Call target that is optimized by Graal upon surpassing a specific invocation threshold.
@@ -136,7 +136,7 @@
         return call(caller, args);
     }
 
-    private void invalidate(Node oldNode, Node newNode, String reason) {
+    private void invalidate(Node oldNode, Node newNode, CharSequence reason) {
         InstalledCode m = this.installedCode;
         if (m != null) {
             CompilerAsserts.neverPartOfCompilation();
@@ -147,7 +147,7 @@
         cancelInstalledTask(oldNode, newNode, reason);
     }
 
-    private void cancelInstalledTask(Node oldNode, Node newNode, String reason) {
+    private void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) {
         Future<InstalledCode> task = this.installedCodeTask;
         if (task != null) {
             task.cancel(true);
@@ -298,7 +298,7 @@
     }
 
     @Override
-    public void nodeReplaced(Node oldNode, Node newNode, String reason) {
+    public void nodeReplaced(Node oldNode, Node newNode, CharSequence reason) {
         compilationProfile.reportNodeReplaced();
         invalidate(oldNode, newNode, reason);
 
@@ -382,7 +382,7 @@
         }
     }
 
-    private static void logOptimizingUnqueued(OptimizedCallTarget target, Node oldNode, Node newNode, String reason) {
+    private static void logOptimizingUnqueued(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) {
         if (TraceTruffleCompilationDetails.getValue()) {
             Map<String, Object> properties = new LinkedHashMap<>();
             addReplaceProperties(properties, oldNode, newNode);
@@ -405,7 +405,7 @@
         }
     }
 
-    private static void logOptimizedInvalidated(OptimizedCallTarget target, Node oldNode, Node newNode, String reason) {
+    private static void logOptimizedInvalidated(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) {
         if (TraceTruffleCompilation.getValue()) {
             Map<String, Object> properties = new LinkedHashMap<>();
             addReplaceProperties(properties, oldNode, newNode);
@@ -414,7 +414,7 @@
         }
     }
 
-    private static void logOptimizingFailed(OptimizedCallTarget callSite, String reason) {
+    private static void logOptimizingFailed(OptimizedCallTarget callSite, CharSequence reason) {
         Map<String, Object> properties = new LinkedHashMap<>();
         properties.put("Reason", reason);
         log(0, "opt fail", callSite.toString(), properties);
@@ -428,11 +428,11 @@
 
             target.getRootNode().accept(new NodeVisitor() {
                 public boolean visit(Node node) {
-                    Kind kind = node.getKind();
-                    if (kind == Kind.POLYMORPHIC || kind == Kind.GENERIC) {
+                    NodeCost kind = node.getCost();
+                    if (kind == NodeCost.POLYMORPHIC || kind == NodeCost.MEGAMORPHIC) {
                         Map<String, Object> props = new LinkedHashMap<>();
                         props.put("simpleName", node.getClass().getSimpleName());
-                        String msg = kind == Kind.GENERIC ? "generic" : "polymorphic";
+                        String msg = kind == NodeCost.MEGAMORPHIC ? "megamorphic" : "polymorphic";
                         log(0, msg, node.toString(), props);
                     }
                     if (node instanceof CallNode) {
@@ -461,8 +461,20 @@
     }
 
     static void addASTSizeProperty(RootNode target, Map<String, Object> properties) {
-        String value = String.format("%4d (%d/%d)", NodeUtil.countNodes(target.getRootNode(), null, true), //
-                        NodeUtil.countNodes(target.getRootNode(), null, Kind.POLYMORPHIC, true), NodeUtil.countNodes(target.getRootNode(), null, Kind.GENERIC, true)); //
+        int polymorphicCount = NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() {
+            public boolean isCounted(Node node) {
+                return node.getCost() == NodeCost.POLYMORPHIC;
+            }
+        }, true);
+
+        int megamorphicCount = NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() {
+            public boolean isCounted(Node node) {
+                return node.getCost() == NodeCost.MEGAMORPHIC;
+            }
+        }, true);
+
+        String value = String.format("%4d (%d/%d)", NodeUtil.countNodes(target.getRootNode(), OptimizedCallNodeProfile.COUNT_FILTER, true), //
+                        polymorphicCount, megamorphicCount); //
 
         properties.put("ASTSize", value);
     }
@@ -521,8 +533,8 @@
                 continue;
             }
 
-            int nodeCount = NodeUtil.countNodes(callTarget.getRootNode(), null, true);
-            int inlinedCallSiteCount = countInlinedNodes(callTarget.getRootNode());
+            int nodeCount = NodeUtil.countNodes(callTarget.getRootNode(), OptimizedCallNodeProfile.COUNT_FILTER, false);
+            int inlinedCallSiteCount = NodeUtil.countNodes(callTarget.getRootNode(), OptimizedCallNodeProfile.COUNT_FILTER, true);
             String comment = callTarget.installedCode == null ? " int" : "";
             comment += callTarget.compilationEnabled ? "" : " fail";
             OUT.printf("%-50s | %10d | %15d | %10d | %3d%s\n", callTarget.getRootNode(), callTarget.callCount, inlinedCallSiteCount, nodeCount,
@@ -536,21 +548,6 @@
         OUT.printf("%-50s | %10d | %15d | %10d | %3d\n", "Total", totalCallCount, totalInlinedCallSiteCount, totalNodeCount, totalInvalidationCount);
     }
 
-    private static int countInlinedNodes(Node rootNode) {
-        List<CallNode> callers = NodeUtil.findAllNodeInstances(rootNode, CallNode.class);
-        int count = 0;
-        for (CallNode callNode : callers) {
-            if (callNode.isInlined()) {
-                count++;
-                RootNode root = callNode.getCurrentRootNode();
-                if (root != null) {
-                    count += countInlinedNodes(root);
-                }
-            }
-        }
-        return count;
-    }
-
     private static void registerCallTarget(OptimizedCallTarget callTarget) {
         callTargets.put(callTarget, 0);
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Mar 20 13:50:21 2014 +0100
@@ -100,7 +100,7 @@
 
         final StructuredGraph graph = new StructuredGraph(executeHelperMethod);
 
-        try (Scope s = Debug.scope("createGraph", graph)) {
+        try (Scope s = Debug.scope("CreateGraph", graph)) {
             new GraphBuilderPhase.Instance(providers.getMetaAccess(), config, TruffleCompilerImpl.Optimizations).apply(graph);
 
             // Replace thisNode with constant.
@@ -250,7 +250,7 @@
         StructuredGraph graph = truffleCache.lookup(targetMethod, arguments, assumptions, canonicalizer);
 
         if (targetMethod.getAnnotation(ExplodeLoop.class) != null) {
-            assert graph.hasLoops();
+            assert graph.hasLoops() : graph + " does not contain a loop";
             final StructuredGraph graphCopy = graph.copy();
             final List<Node> modifiedNodes = new ArrayList<>();
             for (ParameterNode param : graphCopy.getNodes(ParameterNode.class)) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java	Thu Mar 20 13:50:21 2014 +0100
@@ -24,6 +24,8 @@
 
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
+import java.io.*;
+
 public class TimedCompilationPolicy extends DefaultCompilationPolicy {
 
     @Override
@@ -39,9 +41,8 @@
             // maybe introduce another method?
             profile.reportTiminingFailed(timestamp);
             if (TruffleCompilationDecisionTimePrintFail.getValue()) {
-                // Checkstyle: stop
-                System.out.println(profile.getName() + ": timespan  " + (timespan / 1000000) + " ms  larger than threshold");
-                // Checkstyle: resume
+                PrintStream out = System.out;
+                out.println(profile.getName() + ": timespan  " + (timespan / 1000000) + " ms  larger than threshold");
             }
         }
         return false;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Thu Mar 20 13:50:21 2014 +0100
@@ -117,7 +117,7 @@
 
         lastUsed.put(key, counter++);
         cache.put(key, markerGraph);
-        try (Scope s = Debug.scope("TruffleCache", new Object[]{providers.getMetaAccess(), method})) {
+        try (Scope s = Debug.scope("TruffleCache", providers.getMetaAccess(), method)) {
 
             final StructuredGraph graph = new StructuredGraph(method);
             final PhaseContext phaseContext = new PhaseContext(providers, new Assumptions(false));
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Thu Mar 20 13:50:21 2014 +0100
@@ -58,7 +58,7 @@
     @Option(help = "Stop inlining if caller's cumulative tree size would exceed this limit")
     public static final OptionValue<Integer> TruffleInliningMaxCallerSize = new OptionValue<>(2250);
     @Option(help = "Skip inlining candidate if its tree size exceeds this limit")
-    public static final OptionValue<Integer> TruffleInliningMaxCalleeSize = new OptionValue<>(250);
+    public static final OptionValue<Integer> TruffleInliningMaxCalleeSize = new OptionValue<>(350);
     @Option(help = "Call frequency relative to call target")
     public static final OptionValue<Double> TruffleInliningMinFrequency = new OptionValue<>(0.3);
     @Option(help = "Allow inlining of less hot candidates if tree size is small")
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleDebugJavaMethod.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleDebugJavaMethod.java	Thu Mar 20 13:50:21 2014 +0100
@@ -30,7 +30,7 @@
 
 /**
  * Enables a Truffle compilable to masquerade as a {@link JavaMethod} for use as a context value in
- * {@linkplain Debug#scope(String, Object...) debug scopes}.
+ * {@linkplain Debug#scope(Object) debug scopes}.
  */
 public class TruffleDebugJavaMethod implements JavaMethod {
     private final RootCallTarget compilable;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Thu Mar 20 13:50:21 2014 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
+import static com.oracle.graal.debug.Debug.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
@@ -59,8 +61,7 @@
     public boolean runAnalysis(final StructuredGraph graph, final PhaseContextT context) {
         boolean changed = false;
         for (int iteration = 0; iteration < maxIterations; iteration++) {
-
-            try (Scope s = Debug.scope("iteration " + iteration)) {
+            try (Scope s = Debug.scope(isEnabled() ? "iteration " + iteration : null)) {
                 SchedulePhase schedule = new SchedulePhase();
                 schedule.apply(graph, false);
                 Closure<?> closure = createEffectsClosure(context, schedule);
@@ -78,7 +79,9 @@
                 graph.stopTrackingInputChange();
                 graph.stopTrackingUsagesDroppedZero();
 
-                Debug.dump(graph, "after " + getName() + " iteration");
+                if (Debug.isDumpEnabled()) {
+                    Debug.dump(graph, "after " + getName() + " iteration");
+                }
 
                 new DeadCodeEliminationPhase().apply(graph);
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Thu Mar 20 13:50:21 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
+import static com.oracle.graal.debug.Debug.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
@@ -54,7 +55,7 @@
 
     private void runIterations(final StructuredGraph graph, final boolean simple, final HighTierContext context) {
         for (int iteration = 0; iteration < EscapeAnalysisIterations.getValue(); iteration++) {
-            try (Scope s = Debug.scope("iteration " + iteration)) {
+            try (Scope s = Debug.scope(isEnabled() ? "iteration " + iteration : null)) {
                 boolean progress = false;
                 PartialEscapePhase ea = new PartialEscapePhase(false, canonicalizer);
                 boolean eaResult = ea.runAnalysis(graph, context);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Thu Mar 20 13:50:21 2014 +0100
@@ -162,7 +162,7 @@
                     }
                 }
                 if (phi) {
-                    PhiNode phiNode = getCachedPhi(entry, value.getKind());
+                    PhiNode phiNode = getCachedPhi(entry, value.stamp().unrestricted());
                     mergeEffects.addFloatingNode(phiNode, "mergeReadCache");
                     for (int i = 0; i < states.size(); i++) {
                         afterMergeEffects.addPhiInput(phiNode, states.get(i).getReadCache(key.object, key.identity, PEReadEliminationClosure.this));
@@ -194,7 +194,7 @@
                 values[i] = value;
             }
 
-            PhiNode phiNode = getCachedPhi(new ReadCacheEntry(identity, phi), values[0].getKind());
+            PhiNode phiNode = getCachedPhi(new ReadCacheEntry(identity, phi), values[0].stamp().unrestricted());
             mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi");
             for (int i = 0; i < values.length; i++) {
                 afterMergeEffects.addPhiInput(phiNode, values[i]);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Thu Mar 20 13:50:21 2014 +0100
@@ -35,6 +35,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.util.*;
@@ -284,10 +285,10 @@
             super(mergeBlock);
         }
 
-        protected <T> PhiNode getCachedPhi(T virtual, Kind kind) {
+        protected <T> PhiNode getCachedPhi(T virtual, Stamp stamp) {
             PhiNode result = materializedPhis.get(virtual);
             if (result == null) {
-                result = new PhiNode(kind, merge);
+                result = new PhiNode(stamp, merge);
                 materializedPhis.put(virtual, result);
             }
             return result;
@@ -334,8 +335,6 @@
             ObjectState[] objStates = new ObjectState[states.size()];
             boolean materialized;
             do {
-                mergeEffects.clear();
-                afterMergeEffects.clear();
                 materialized = false;
                 for (VirtualObjectNode object : virtualObjTemp) {
                     for (int i = 0; i < objStates.length; i++) {
@@ -363,7 +362,7 @@
                         if (uniqueMaterializedValue != null) {
                             newState.addObject(object, new ObjectState(object, uniqueMaterializedValue, EscapeState.Materialized, null));
                         } else {
-                            PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object);
+                            PhiNode materializedValuePhi = getCachedPhi(object, StampFactory.forKind(Kind.Object));
                             mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi");
                             for (int i = 0; i < objStates.length; i++) {
                                 ObjectState obj = objStates[i];
@@ -381,6 +380,11 @@
                         materialized |= processPhi(phi, states, virtualObjTemp);
                     }
                 }
+                if (materialized) {
+                    newState.objectStates.clear();
+                    mergeEffects.clear();
+                    afterMergeEffects.clear();
+                }
             } while (materialized);
         }
 
@@ -458,7 +462,7 @@
                     for (int i = 1; i < objStates.length; i++) {
                         ValueNode[] fields = objStates[i].getEntries();
                         if (phis[valueIndex] == null && values[valueIndex] != fields[valueIndex]) {
-                            phis[valueIndex] = new PhiNode(values[valueIndex].getKind(), merge);
+                            phis[valueIndex] = new PhiNode(values[valueIndex].stamp().unrestricted(), merge);
                         }
                     }
                     if (twoSlotKinds != null && twoSlotKinds[valueIndex] != null) {
@@ -487,7 +491,7 @@
                 return materialized;
             } else {
                 // not compatible: materialize in all predecessors
-                PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object);
+                PhiNode materializedValuePhi = getCachedPhi(object, StampFactory.forKind(Kind.Object));
                 for (int i = 0; i < blockStates.size(); i++) {
                     ObjectState obj = objStates[i];
                     Block predecessor = mergeBlock.getPredecessors().get(i);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Thu Mar 20 13:50:21 2014 +0100
@@ -33,6 +33,7 @@
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
@@ -196,10 +197,10 @@
             super(mergeBlock);
         }
 
-        protected <T> PhiNode getCachedPhi(T virtual, Kind kind) {
+        protected <T> PhiNode getCachedPhi(T virtual, Stamp stamp) {
             PhiNode result = materializedPhis.get(virtual);
             if (result == null) {
-                result = new PhiNode(kind, merge);
+                result = new PhiNode(stamp, merge);
                 materializedPhis.put(virtual, result);
             }
             return result;
@@ -229,7 +230,7 @@
                     }
                 }
                 if (phi) {
-                    PhiNode phiNode = getCachedPhi(entry, value.getKind());
+                    PhiNode phiNode = getCachedPhi(entry, value.stamp().unrestricted());
                     mergeEffects.addFloatingNode(phiNode, "mergeReadCache");
                     for (int i = 0; i < states.size(); i++) {
                         afterMergeEffects.addPhiInput(phiNode, states.get(i).getCacheEntry(key));
@@ -262,7 +263,7 @@
             }
 
             CacheEntry<?> newIdentifier = identifier.duplicateWithObject(phi);
-            PhiNode phiNode = getCachedPhi(newIdentifier, values[0].getKind());
+            PhiNode phiNode = getCachedPhi(newIdentifier, values[0].stamp().unrestricted());
             mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi");
             for (int i = 0; i < values.length; i++) {
                 afterMergeEffects.addPhiInput(phiNode, values[i]);
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -69,7 +69,7 @@
     @Override
     public void generate(LIRGeneratorTool generator) {
         assert getKind() != input.getKind();
-        assert generator.target().arch.getSizeInBytes(getKind()) == generator.target().arch.getSizeInBytes(input.getKind());
+        assert generator.target().getSizeInBytes(getKind()) == generator.target().getSizeInBytes(input.getKind());
 
         AllocatableValue result = generator.newVariable(getKind());
         generator.emitMove(result, generator.operand(input));
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -71,6 +71,7 @@
     public void testImplicitCast0() {
         ImplicitCast0Node node = ImplicitCast0NodeFactory.create(null);
         TestRootNode<ImplicitCast0Node> root = new TestRootNode<>(node);
+        root.adoptChildren();
         Assert.assertEquals("2", root.getNode().executeEvaluated(null, "2"));
         Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
         Assert.assertEquals("1", root.getNode().executeEvaluated(null, "1"));
@@ -106,6 +107,7 @@
     public void testImplicitCast1() {
         ImplicitCast1Node node = ImplicitCast1NodeFactory.create(null);
         TestRootNode<ImplicitCast1Node> root = new TestRootNode<>(node);
+        root.adoptChildren();
         Assert.assertEquals("2", root.getNode().executeEvaluated(null, "2"));
         Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
         Assert.assertEquals("1", root.getNode().executeEvaluated(null, "1"));
@@ -146,6 +148,7 @@
     public void testImplicitCast2() {
         ImplicitCast2Node node = ImplicitCast2NodeFactory.create(null, null);
         TestRootNode<ImplicitCast2Node> root = new TestRootNode<>(node);
+        root.adoptChildren();
         Assert.assertEquals("42", root.getNode().executeEvaluated(null, "4", "2"));
         Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1, 1));
         Assert.assertEquals("42", root.getNode().executeEvaluated(null, "4", "2"));
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -33,7 +33,6 @@
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 
 public class PolymorphicTest {
 
@@ -55,7 +54,7 @@
         assertEquals("(boolean,boolean)", executeWith(node, false, false));
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals(Kind.SPECIALIZED, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -65,7 +64,7 @@
         TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.NONE, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -76,7 +75,7 @@
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(boolean,boolean)", executeWith(node, true, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.NONE, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -88,7 +87,7 @@
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(boolean,boolean)", executeWith(node, true, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -97,7 +96,7 @@
     public void testGenericInitial() {
         TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
         assertEquals("(generic,generic)", executeWith(node, "1", "1"));
-        assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -108,7 +107,7 @@
         assertEquals("(boolean,int)", executeWith(node, false, 42));
         assertEquals("(boolean,boolean)", executeWith(node, false, false));
         assertEquals("(generic,generic)", executeWith(node, "", ""));
-        assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
         /* Assertions for bug GRAAL-425 */
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Thu Mar 20 13:50:21 2014 +0100
@@ -32,7 +32,6 @@
 import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Node1Factory;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 
 public class PolymorphicTest2 {
 
@@ -43,7 +42,7 @@
         assertEquals(21, executeWith(node, false, false));
         assertEquals(42, executeWith(node, 21, 21));
         assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.NONE, node.getNode().getCost());
     }
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Thu Mar 20 13:50:21 2014 +0100
@@ -76,11 +76,15 @@
     }
 
     static <E extends ValueNode> TestRootNode<E> createRoot(NodeFactory<E> factory, Object... constants) {
-        return new TestRootNode<>(createNode(factory, constants));
+        TestRootNode<E> rootNode = new TestRootNode<>(createNode(factory, constants));
+        rootNode.adoptChildren();
+        return rootNode;
     }
 
     static <E extends ValueNode> TestRootNode<E> createGenericRoot(NodeFactory<E> factory, Object... constants) {
-        return new TestRootNode<>(createGenericNode(factory, constants));
+        TestRootNode<E> rootNode = new TestRootNode<>(createGenericNode(factory, constants));
+        rootNode.adoptChildren();
+        return rootNode;
     }
 
     static CallTarget createCallTarget(ValueNode node) {
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -100,7 +100,7 @@
 
         public TestRootNode(E node) {
             super(null);
-            this.node = adoptChild(node);
+            this.node = node;
         }
 
         @Override
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -61,7 +61,7 @@
         Assert.assertEquals(42, result);
     }
 
-    class TestArguments extends Arguments {
+    private static class TestArguments extends Arguments {
 
         final int[] values;
 
@@ -70,13 +70,13 @@
         }
     }
 
-    class TestRootNode extends RootNode {
+    private static class TestRootNode extends RootNode {
 
-        @Children private TestArgumentNode[] children;
+        @Children private final TestArgumentNode[] children;
 
         TestRootNode(TestArgumentNode[] children) {
             super(null);
-            this.children = adoptChildren(children);
+            this.children = children;
         }
 
         @Override
@@ -89,7 +89,7 @@
         }
     }
 
-    class TestArgumentNode extends Node {
+    private static class TestArgumentNode extends Node {
 
         private final int index;
 
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -61,13 +61,13 @@
         TestChildNode leftChild = new TestChildNode();
         TestChildNode rightChild = new TestChildNode();
         TestRootNode rootNode = new TestRootNode(leftChild, rightChild);
+        CallTarget target = runtime.createCallTarget(rootNode);
         Assert.assertEquals(rootNode, leftChild.getParent());
         Assert.assertEquals(rootNode, rightChild.getParent());
         Iterator<Node> iterator = rootNode.getChildren().iterator();
         Assert.assertEquals(leftChild, iterator.next());
         Assert.assertEquals(rightChild, iterator.next());
         Assert.assertFalse(iterator.hasNext());
-        CallTarget target = runtime.createCallTarget(rootNode);
         Object result = target.call();
         Assert.assertEquals(42, result);
     }
@@ -79,8 +79,8 @@
 
         public TestRootNode(TestChildNode left, TestChildNode right) {
             super(null);
-            this.left = adoptChild(left);
-            this.right = adoptChild(right);
+            this.left = left;
+            this.right = right;
         }
 
         @Override
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -55,13 +55,13 @@
         TestChildNode firstChild = new TestChildNode();
         TestChildNode secondChild = new TestChildNode();
         TestRootNode rootNode = new TestRootNode(new TestChildNode[]{firstChild, secondChild});
+        CallTarget target = runtime.createCallTarget(rootNode);
         Assert.assertEquals(rootNode, firstChild.getParent());
         Assert.assertEquals(rootNode, secondChild.getParent());
         Iterator<Node> iterator = rootNode.getChildren().iterator();
         Assert.assertEquals(firstChild, iterator.next());
         Assert.assertEquals(secondChild, iterator.next());
         Assert.assertFalse(iterator.hasNext());
-        CallTarget target = runtime.createCallTarget(rootNode);
         Object result = target.call();
         Assert.assertEquals(42, result);
     }
@@ -72,7 +72,7 @@
 
         public TestRootNode(TestChildNode[] children) {
             super(null);
-            this.children = adoptChildren(children);
+            this.children = children;
         }
 
         @Override
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -60,13 +60,13 @@
         Assert.assertEquals(42, result);
     }
 
-    class TestRootNode extends RootNode {
+    private static class TestRootNode extends RootNode {
 
-        @Children TestChildNode[] children;
+        @Children private final TestChildNode[] children;
 
         public TestRootNode(TestChildNode[] children) {
             super(null);
-            this.children = adoptChildren(children);
+            this.children = children;
         }
 
         @Override
@@ -79,7 +79,7 @@
         }
     }
 
-    class TestChildNode extends Node {
+    private static class TestChildNode extends Node {
 
         private final int value;
 
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -64,8 +64,8 @@
 
         public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
             super(null, descriptor);
-            this.left = adoptChild(left);
-            this.right = adoptChild(right);
+            this.left = left;
+            this.right = right;
         }
 
         @Override
@@ -108,7 +108,7 @@
 
         IntAssignLocal(FrameSlot slot, TestChildNode value) {
             super(slot);
-            this.value = adoptChild(value);
+            this.value = value;
         }
 
         @Override
@@ -130,7 +130,7 @@
 
         ObjectAssignLocal(FrameSlot slot, TestChildNode value) {
             super(slot);
-            this.value = adoptChild(value);
+            this.value = value;
         }
 
         @Override
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -88,8 +88,8 @@
 
         public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
             super(null, descriptor);
-            this.left = adoptChild(left);
-            this.right = adoptChild(right);
+            this.left = left;
+            this.right = right;
         }
 
         @Override
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -59,13 +59,13 @@
         UnresolvedNode leftChild = new UnresolvedNode("20");
         UnresolvedNode rightChild = new UnresolvedNode("22");
         TestRootNode rootNode = new TestRootNode(new ValueNode[]{leftChild, rightChild});
+        CallTarget target = runtime.createCallTarget(rootNode);
         assertEquals(rootNode, leftChild.getParent());
         assertEquals(rootNode, rightChild.getParent());
         Iterator<Node> iterator = rootNode.getChildren().iterator();
         Assert.assertEquals(leftChild, iterator.next());
         Assert.assertEquals(rightChild, iterator.next());
         Assert.assertFalse(iterator.hasNext());
-        CallTarget target = runtime.createCallTarget(rootNode);
         Object result = target.call();
         assertEquals(42, result);
         assertEquals(42, target.call());
@@ -85,7 +85,7 @@
 
         public TestRootNode(ValueNode[] children) {
             super(null);
-            this.children = adoptChildren(children);
+            this.children = children;
         }
 
         @Override
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -63,8 +63,8 @@
 
         public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
             super(null, descriptor);
-            this.left = adoptChild(left);
-            this.right = adoptChild(right);
+            this.left = left;
+            this.right = right;
         }
 
         @Override
@@ -115,7 +115,7 @@
 
         IntAssignLocal(FrameSlot slot, TestChildNode value) {
             super(slot);
-            this.value = adoptChild(value);
+            this.value = value;
         }
 
         @Override
@@ -137,7 +137,7 @@
 
         ObjectAssignLocal(FrameSlot slot, TestChildNode value) {
             super(slot);
-            this.value = adoptChild(value);
+            this.value = value;
         }
 
         @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2014, 2014, 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.truffle.api.test;
+
+import static org.junit.Assert.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Test node rewriting in a tree shared across multiple threads (run with -ea).
+ */
+public class ThreadSafetyTest {
+
+    @Test
+    public void test() throws InterruptedException {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestRootNode rootNode1 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new ConstNode(42)))))));
+        final CallTarget target1 = runtime.createCallTarget(rootNode1);
+        NodeUtil.verify(rootNode1);
+
+        RecursiveCallNode callNode = new RecursiveCallNode(new ConstNode(42));
+        TestRootNode rootNode2 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(callNode))))));
+        final CallTarget target2 = runtime.createCallTarget(rootNode2);
+        callNode.setCallNode(runtime.createCallNode(target2));
+        NodeUtil.verify(rootNode2);
+
+        testTarget(target1, 47, 1_000_000);
+        testTarget(target2, 72, 1_000_000);
+    }
+
+    private static void testTarget(final CallTarget target, final int expectedResult, final int numberOfIterations) throws InterruptedException {
+        ExecutorService executorService = Executors.newFixedThreadPool(20);
+        final AtomicInteger ai = new AtomicInteger();
+        for (int i = 0; i < numberOfIterations; i++) {
+            executorService.submit(new Runnable() {
+                public void run() {
+                    try {
+                        Object result = target.call(new TestArguments(5));
+                        assertEquals(expectedResult, result);
+                        ai.incrementAndGet();
+                    } catch (Throwable t) {
+                        PrintStream out = System.out;
+                        out.println(t);
+                    }
+                }
+            });
+        }
+        executorService.shutdown();
+        executorService.awaitTermination(30, TimeUnit.SECONDS);
+        assertEquals(numberOfIterations, ai.get());
+    }
+
+    static class TestArguments extends Arguments {
+        final int arg;
+
+        public TestArguments(int arg) {
+            this.arg = arg;
+        }
+    }
+
+    static class TestRootNode extends RootNode {
+
+        @Child private ValueNode child;
+
+        public TestRootNode(ValueNode child) {
+            super(null);
+            this.child = child;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return child.execute(frame);
+        }
+    }
+
+    abstract static class ValueNode extends Node {
+
+        public ValueNode() {
+            super(null);
+        }
+
+        abstract int execute(VirtualFrame frame);
+    }
+
+    static class RewritingNode extends ValueNode {
+
+        @Child private ValueNode child;
+        private final Random random;
+
+        public RewritingNode(ValueNode child) {
+            this(child, new Random());
+        }
+
+        public RewritingNode(ValueNode child, Random random) {
+            this.child = child;
+            this.random = random;
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            boolean replace = random.nextBoolean();
+            if (replace) {
+                ValueNode newNode = this.replace(new OtherRewritingNode(child, random));
+                return newNode.execute(frame);
+            }
+            return 1 + child.execute(frame);
+        }
+    }
+
+    static class OtherRewritingNode extends ValueNode {
+
+        @Child private ValueNode child;
+        private final Random random;
+
+        public OtherRewritingNode(ValueNode child, Random random) {
+            this.child = child;
+            this.random = random;
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            boolean replace = random.nextBoolean();
+            if (replace) {
+                ValueNode newNode = this.replace(new RewritingNode(child, random));
+                return newNode.execute(frame);
+            }
+            return 1 + child.execute(frame);
+        }
+    }
+
+    static class ConstNode extends ValueNode {
+
+        private final int value;
+
+        ConstNode(int value) {
+            this.value = value;
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            return value;
+        }
+    }
+
+    static class RecursiveCallNode extends ValueNode {
+        @Child CallNode callNode;
+        @Child private ValueNode valueNode;
+
+        RecursiveCallNode(ValueNode value) {
+            this.valueNode = value;
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            int arg = frame.getArguments(TestArguments.class).arg;
+            if (arg > 0) {
+                return (int) callNode.call(frame.pack(), new TestArguments(arg - 1));
+            } else {
+                return valueNode.execute(frame);
+            }
+        }
+
+        void setCallNode(CallNode callNode) {
+            this.callNode = insert(callNode);
+        }
+    }
+}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderDeserializerTest.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderDeserializerTest.java	Thu Mar 20 13:50:21 2014 +0100
@@ -151,6 +151,8 @@
             return;
         }
 
+        expectedAst.adoptChildren();
+
         Assert.assertNotNull(actualAst);
         // fields are asserted using the corresponding equals implementation
         Assert.assertEquals(expectedAst, actualAst);
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestNodes.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestNodes.java	Thu Mar 20 13:50:21 2014 +0100
@@ -84,7 +84,7 @@
         @Child Node child;
 
         public NodeWithOneChild(Node child) {
-            this.child = adoptChild(child);
+            this.child = child;
         }
 
     }
@@ -95,8 +95,8 @@
         @Child Node child2;
 
         public NodeWithTwoChilds(Node child1, Node child2) {
-            this.child1 = adoptChild(child1);
-            this.child2 = adoptChild(child2);
+            this.child1 = child1;
+            this.child2 = child2;
         }
 
     }
@@ -108,9 +108,9 @@
         @Child Node child3;
 
         public NodeWithThreeChilds(Node child1, Node child2, Node child3) {
-            this.child1 = adoptChild(child1);
-            this.child2 = adoptChild(child2);
-            this.child3 = adoptChild(child3);
+            this.child1 = child1;
+            this.child2 = child2;
+            this.child3 = child3;
         }
 
     }
@@ -120,7 +120,7 @@
         @Children private final Node[] childNodes;
 
         NodeWithArray(Node[] children) {
-            this.childNodes = adoptChildren(children);
+            this.childNodes = children;
         }
 
         Node[] getChildNodes() {
@@ -134,8 +134,8 @@
         @Children private final Node[] childNodes2;
 
         NodeWithTwoArray(Node[] childs1, Node[] childs2) {
-            this.childNodes1 = adoptChildren(childs1);
-            this.childNodes2 = adoptChildren(childs2);
+            this.childNodes1 = childs1;
+            this.childNodes2 = childs2;
         }
 
         Node[] getChildNodes1() {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ReplaceObserver.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ReplaceObserver.java	Thu Mar 20 13:50:21 2014 +0100
@@ -31,5 +31,5 @@
  */
 public interface ReplaceObserver {
 
-    void nodeReplaced(Node oldNode, Node newNode, String reason);
+    void nodeReplaced(Node oldNode, Node newNode, CharSequence reason);
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java	Thu Mar 20 13:50:21 2014 +0100
@@ -37,6 +37,7 @@
     public RootCallTarget(RootNode function) {
         this.rootNode = function;
         this.rootNode.setCallTarget(this);
+        this.rootNode.adoptChildren();
     }
 
     @Override
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Thu Mar 20 13:50:21 2014 +0100
@@ -25,7 +25,6 @@
 package com.oracle.truffle.api;
 
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 
 /**
  * Class containing general Truffle options.
@@ -56,29 +55,29 @@
     public static String TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass");
 
     /**
-     * Filters rewrites which does not contain the {@link Kind} in its source {@link NodeInfo}. If
-     * no {@link NodeInfo} is defined the element is filtered if the filter value is set.
+     * Filters rewrites which does not contain the {@link NodeCost} in its source {@link NodeInfo}.
+     * If no {@link NodeInfo} is defined the element is filtered if the filter value is set.
      * <p>
      * Can be set with
-     * {@code -Dtruffle.TraceRewritesFilterFromKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}.
+     * {@code -Dtruffle.TraceRewritesFilterFromCost=NONE|MONOMORPHIC|POLYMORPHIC|MEGAMORPHIC}.
      */
-    public static NodeInfo.Kind TraceRewritesFilterFromKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromKind"));
+    public static NodeCost TraceRewritesFilterFromCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromCost"));
 
     /**
-     * Filters rewrites which does not contain the {@link Kind} in its target {@link NodeInfo}. If
-     * no {@link NodeInfo} is defined the element is filtered if the filter value is set.
+     * Filters rewrites which does not contain the {@link NodeCost} in its target {@link NodeInfo}.
+     * If no {@link NodeInfo} is defined the element is filtered if the filter value is set.
      * <p>
      * Can be set with
      * {@code -Dtruffle.TraceRewritesFilterToKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}.
      */
-    public static NodeInfo.Kind TraceRewritesFilterToKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToKind"));
+    public static NodeCost TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost"));
 
-    private static NodeInfo.Kind parseNodeInfoKind(String kind) {
+    private static NodeCost parseNodeInfoKind(String kind) {
         if (kind == null) {
             return null;
         }
 
-        return NodeInfo.Kind.valueOf(kind);
+        return NodeCost.valueOf(kind);
     }
 
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java	Thu Mar 20 13:50:21 2014 +0100
@@ -26,7 +26,6 @@
 
 import com.oracle.truffle.api.nodes.*;
 
-// TODO (mlvdv) does this need to extend ControlFlowException?  It was originally part of the Ruby Shell.
 /**
  * Controls breaking out of an execution context, such as a shell or eval.
  */
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java	Thu Mar 20 13:50:21 2014 +0100
@@ -26,7 +26,6 @@
 
 import com.oracle.truffle.api.nodes.*;
 
-//TODO (mlvdv) does this need to extend ControlFlowException?  It was originally part of the Ruby execution environment.
 /**
  * Controls breaking out of all executions and ending Truffle execution.
  */
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -64,6 +64,11 @@
     }
 
     @Override
+    public boolean isInlinable() {
+        return false;
+    }
+
+    @Override
     public String toString() {
         return getParent() != null ? getParent().toString() : super.toString();
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -28,13 +28,18 @@
 import com.oracle.truffle.api.frame.*;
 
 /**
- * This node represents a call to a static {@link CallTarget}. This node should be used whenever a
- * {@link CallTarget} is considered constant at a certain location in the tree. This enables the
- * Truffle runtime to perform inlining or other optimizations for this call-site. This class is
- * intended to be implemented by truffle runtime implementors and not by guest language
- * implementors.
+ * Represents a call to a {@link CallTarget} in the Truffle AST. Addtionally to calling the
+ * {@link CallTarget} this {@link Node} enables the runtime system to implement further
+ * optimizations. Optimizations that can possibly applied to a {@link CallNode} are inlining and
+ * splitting. Inlining inlines this call site into the call graph of the parent {@link CallTarget}.
+ * Splitting duplicates the {@link CallTarget} using {@link RootNode#split()} to collect call site
+ * sensitive profiling information.
  * 
- * @see #create(CallTarget) to create a CallNode instance.
+ * Please note: This class is not intended to be subclassed by guest language implementations.
+ * 
+ * @see TruffleRuntime#createCallNode(CallTarget)
+ * @see #inline()
+ * @see #split()
  */
 public abstract class CallNode extends Node {
 
@@ -45,7 +50,7 @@
     }
 
     /**
-     * Calls this constant target passing a caller frame and arguments.
+     * Calls the inner {@link CallTarget} returned by {@link #getCurrentCallTarget()}.
      * 
      * @param caller the caller frame
      * @param arguments the arguments that should be passed to the callee
@@ -65,27 +70,63 @@
     }
 
     /**
-     * @return true if this {@link CallNode} was already inlined.
+     * Returns <code>true</code> if the underlying runtime system supports inlining for the
+     * {@link CallTarget} in this {@link CallNode}.
+     * 
+     * @return true if inlining is supported.
+     */
+    public abstract boolean isInlinable();
+
+    /**
+     * Returns <code>true</code> if the {@link CallTarget} in this {@link CallNode} is inlined. A
+     * {@link CallNode} can either be inlined manually by invoking {@link #inline()} or by the
+     * runtime system which may at any point decide to inline.
+     * 
+     * @return true if this method was inlined else false.
      */
     public abstract boolean isInlined();
 
+    /**
+     * Enforces the runtime system to inline the {@link CallTarget} at this call site. If the
+     * runtime system does not support inlining or it is already inlined this method has no effect.
+     */
     public abstract void inline();
 
+    /**
+     * Returns <code>true</code> if this {@link CallNode} can be split. A {@link CallNode} can only
+     * be split if the runtime system supports splitting and if the {@link RootNode} contained the
+     * {@link CallTarget} returns <code>true</code> for {@link RootNode#isSplittable()}.
+     * 
+     * @return <code>true</code> if the target can be split
+     */
     public abstract boolean isSplittable();
 
+    /**
+     * Enforces the runtime system to split the {@link CallTarget}. If the {@link CallNode} is not
+     * splittable this methods has no effect.
+     */
     public abstract boolean split();
 
+    /**
+     * Returns <code>true</code> if the target of the {@link CallNode} was split.
+     * 
+     * @return if the target was split
+     */
     public final boolean isSplit() {
         return getSplitCallTarget() != null;
     }
 
+    /**
+     * Returns the splitted {@link CallTarget} if this method is split.
+     * 
+     * @return the split {@link CallTarget}
+     */
     public abstract CallTarget getSplitCallTarget();
 
     /**
      * Returns the used call target when {@link #call(PackedFrame, Arguments)} is invoked. If the
-     * {@link CallNode} was split this method returns the {@link CallTarget} returned by
-     * {@link #getSplitCallTarget()}. If not split this method returns the original supplied
-     * {@link CallTarget}.
+     * {@link CallTarget} was split this method returns the {@link CallTarget} returned by
+     * {@link #getSplitCallTarget()}.
      * 
      * @return the used {@link CallTarget} when node is called
      */
@@ -98,8 +139,24 @@
         }
     }
 
+    /**
+     * Returns the {@link RootNode} associated with {@link CallTarget} returned by
+     * {@link #getCurrentCallTarget()}. If the stored {@link CallTarget} does not contain a
+     * {@link RootNode} this method returns <code>null</code>.
+     * 
+     * @see #getCurrentCallTarget()
+     * @return the root node of the used call target
+     */
+    public final RootNode getCurrentRootNode() {
+        CallTarget target = getCurrentCallTarget();
+        if (target instanceof RootCallTarget) {
+            return ((RootCallTarget) target).getRootNode();
+        }
+        return null;
+    }
+
     @Override
-    protected void onReplace(Node newNode, String reason) {
+    protected void onReplace(Node newNode, CharSequence reason) {
         super.onReplace(newNode, reason);
 
         /*
@@ -114,6 +171,9 @@
         registerCallTarget((CallNode) newNode);
     }
 
+    /**
+     * Internal API for the runtime system.
+     */
     protected static final void registerCallTarget(CallNode newNode) {
         RootNode newRoot = newNode.getCurrentRootNode();
         if (newRoot != null) {
@@ -121,51 +181,4 @@
         }
     }
 
-    protected void notifyCallNodeAdded() {
-
-    }
-
-    /**
-     * Returns the {@link RootNode} associated with {@link CallTarget} returned by
-     * {@link #getCurrentCallTarget()}.
-     * 
-     * @see #getCurrentCallTarget()
-     * @return the root node of the used call target
-     */
-    public final RootNode getCurrentRootNode() {
-        CallTarget target = getCurrentCallTarget();
-        if (target instanceof RootCallTarget) {
-            return ((RootCallTarget) target).getRootNode();
-        }
-        return null;
-    }
-
-    /**
-     * @deprecated always returns <code>true</code> now.
-     */
-    @Deprecated
-    public boolean isInlinable() {
-        return true;
-    }
-
-    /**
-     * @deprecated instead use {@link #getCurrentRootNode()} and check for {@link #isInlined()} for
-     *             true.
-     */
-    @Deprecated
-    public RootNode getInlinedRoot() {
-        if (!isInlined()) {
-            return null;
-        }
-        return getCurrentRootNode();
-    }
-
-    /**
-     * @deprecated use {@link TruffleRuntime#createCallNode(CallTarget)} instead
-     */
-    @Deprecated
-    public static CallNode create(CallTarget target) {
-        return Truffle.getRuntime().createCallNode(target);
-    }
-
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Thu Mar 20 13:50:21 2014 +0100
@@ -214,7 +214,7 @@
             setNodeProperty(node, "name", node.getClass().getSimpleName().replaceFirst("Node$", ""));
             NodeInfo nodeInfo = node.getClass().getAnnotation(NodeInfo.class);
             if (nodeInfo != null) {
-                setNodeProperty(node, "kind", nodeInfo.kind());
+                setNodeProperty(node, "cost", nodeInfo.cost());
                 if (!nodeInfo.shortName().isEmpty()) {
                     setNodeProperty(node, "shortName", nodeInfo.shortName());
                 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Thu Mar 20 13:50:21 2014 +0100
@@ -27,9 +27,9 @@
 import java.io.*;
 import java.lang.annotation.*;
 import java.util.*;
+import java.util.concurrent.*;
 
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 
 /**
  * Abstract base class for all Truffle nodes.
@@ -82,12 +82,20 @@
         this.sourceSection = section;
     }
 
-    public Kind getKind() {
+    /**
+     * Returns a rough estimate for the cost of this {@link Node}. This estimate can be used by
+     * runtime systems or guest languages to implement heuristics based on Truffle ASTs. This method
+     * is intended to be overridden by subclasses. The default implementation returns the value of
+     * {@link NodeInfo#cost()} of the {@link NodeInfo} annotation declared at the subclass. If no
+     * {@link NodeInfo} annotation is declared the method returns {@link NodeCost#MONOMORPHIC} as a
+     * default value.
+     */
+    public NodeCost getCost() {
         NodeInfo info = getClass().getAnnotation(NodeInfo.class);
         if (info != null) {
-            return info.kind();
+            return info.cost();
         }
-        return Kind.SPECIALIZED;
+        return NodeCost.MONOMORPHIC;
     }
 
     /**
@@ -126,11 +134,36 @@
      * @param newChildren the array of new children whose parent should be updated
      * @return the array of new children
      */
-    protected final <T extends Node> T[] adoptChildren(T[] newChildren) {
-        if (newChildren != null) {
-            for (T n : newChildren) {
-                adoptChild(n);
-            }
+    @SuppressWarnings("static-method")
+    @Deprecated
+    protected final <T extends Node> T[] adoptChildren(final T[] newChildren) {
+        return newChildren;
+    }
+
+    /**
+     * Method that updates the link to the parent in the specified new child node to this node.
+     * 
+     * @param newChild the new child whose parent should be updated
+     * @return the new child
+     */
+    @SuppressWarnings("static-method")
+    @Deprecated
+    protected final <T extends Node> T adoptChild(final T newChild) {
+        return newChild;
+    }
+
+    /**
+     * Method that updates the link to the parent in the array of specified new child nodes to this
+     * node.
+     * 
+     * @param newChildren the array of new children whose parent should be updated
+     * @return the array of new children
+     */
+    protected final <T extends Node> T[] insert(final T[] newChildren) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        assert newChildren != null;
+        for (Node newChild : newChildren) {
+            adoptHelper(newChild);
         }
         return newChildren;
     }
@@ -141,14 +174,52 @@
      * @param newChild the new child whose parent should be updated
      * @return the new child
      */
-    protected final <T extends Node> T adoptChild(T newChild) {
-        if (newChild != null) {
-            if (newChild == this) {
-                throw new IllegalStateException("The parent of a node can never be the node itself.");
+    protected final <T extends Node> T insert(final T newChild) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        assert newChild != null;
+        adoptHelper(newChild);
+        return newChild;
+    }
+
+    public final void adoptChildren() {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        adoptHelper();
+    }
+
+    private void adoptHelper(final Node newChild) {
+        assert newChild != null;
+        if (newChild == this) {
+            throw new IllegalStateException("The parent of a node can never be the node itself.");
+        }
+        newChild.parent = this;
+        newChild.adoptHelper();
+    }
+
+    private void adoptHelper() {
+        Iterable<Node> children = this.getChildren();
+        for (Node child : children) {
+            if (child != null && child.getParent() != this) {
+                this.adoptHelper(child);
             }
-            ((Node) newChild).parent = this;
+        }
+    }
+
+    private void adoptUnadoptedHelper(final Node newChild) {
+        assert newChild != null;
+        if (newChild == this) {
+            throw new IllegalStateException("The parent of a node can never be the node itself.");
         }
-        return newChild;
+        newChild.parent = this;
+        newChild.adoptUnadoptedHelper();
+    }
+
+    private void adoptUnadoptedHelper() {
+        Iterable<Node> children = this.getChildren();
+        for (Node child : children) {
+            if (child != null && child.getParent() == null) {
+                this.adoptUnadoptedHelper(child);
+            }
+        }
     }
 
     /**
@@ -179,54 +250,17 @@
      * @param reason a description of the reason for the replacement
      * @return the new node
      */
-    public final <T extends Node> T replace(T newNode, String reason) {
+    public final <T extends Node> T replace(final T newNode, final CharSequence reason) {
         CompilerDirectives.transferToInterpreterAndInvalidate();
-        if (this.getParent() == null) {
-            throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent.");
-        }
-        if (sourceSection != null && newNode.getSourceSection() == null) {
-            // Pass on the source section to the new node.
-            newNode.assignSourceSection(sourceSection);
-        }
-        onReplace(newNode, reason);
-        ((Node) newNode).parent = this.parent;
-        if (!NodeUtil.replaceChild(this.parent, this, newNode)) {
-            fixupTree();
-        }
-        reportReplace(this, newNode, reason);
+        atomic(new Runnable() {
+            public void run() {
+                replaceHelper(newNode, reason);
+            }
+        });
         return newNode;
     }
 
     /**
-     * Rewrite has failed; the tree is likely inconsistent, so fix any stale parent references.
-     * 
-     * This is a rather expensive operation but rare to occur.
-     */
-    private void fixupTree() {
-        Node rootNode = getRootNode();
-        if (rootNode == null) {
-            throw new UnsupportedOperationException("Tree does not have a root node.");
-        }
-        int fixCount = rootNode.fixupChildren();
-        assert fixCount != 0 : "sanity check failed: missing @Child[ren] or adoptChild?";
-        // if nothing had to be fixed, rewrite failed due to node not being a proper child.
-    }
-
-    private int fixupChildren() {
-        int fixCount = 0;
-        for (Node child : getChildren()) {
-            if (child != null) {
-                if (child.parent != this) {
-                    child.parent = this;
-                    fixCount++;
-                }
-                fixCount += child.fixupChildren();
-            }
-        }
-        return fixCount;
-    }
-
-    /**
      * Replaces this node with another node. If there is a source section (see
      * {@link #getSourceSection()}) associated with this node, it is transferred to the new node.
      * 
@@ -237,6 +271,27 @@
         return replace(newNode, "");
     }
 
+    private void replaceHelper(Node newNode, CharSequence reason) {
+        CompilerAsserts.neverPartOfCompilation();
+        if (this.getParent() == null) {
+            throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent.");
+        }
+        if (sourceSection != null && newNode.getSourceSection() == null) {
+            // Pass on the source section to the new node.
+            newNode.assignSourceSection(sourceSection);
+        }
+        // (aw) need to set parent *before* replace, so that (unsynchronized) getRootNode()
+        // will always find the root node
+        newNode.parent = this.parent;
+        if (NodeUtil.replaceChild(this.parent, this, newNode)) {
+            this.parent.adoptHelper(newNode);
+        } else {
+            this.parent.adoptUnadoptedHelper(newNode);
+        }
+        reportReplace(this, newNode, reason);
+        onReplace(newNode, reason);
+    }
+
     /**
      * Checks if this node is properly adopted by a parent and can be replaced.
      * 
@@ -253,7 +308,7 @@
         return false;
     }
 
-    private void reportReplace(Node oldNode, Node newNode, String reason) {
+    private void reportReplace(Node oldNode, Node newNode, CharSequence reason) {
         RootNode rootNode = getRootNode();
         if (rootNode != null) {
             CallTarget target = rootNode.getCallTarget();
@@ -270,68 +325,61 @@
      * @param newNode the replacement node
      * @param reason the reason the replace supplied
      */
-    protected void onReplace(Node newNode, String reason) {
+    protected void onReplace(Node newNode, CharSequence reason) {
         if (TruffleOptions.TraceRewrites) {
             traceRewrite(newNode, reason);
         }
     }
 
-    private void traceRewrite(Node newNode, String reason) {
-        Class<? extends Node> from = getClass();
-        Class<? extends Node> to = newNode.getClass();
+    private void traceRewrite(Node newNode, CharSequence reason) {
 
-        if (TruffleOptions.TraceRewritesFilterFromKind != null) {
-            if (filterByKind(from, TruffleOptions.TraceRewritesFilterFromKind)) {
+        if (TruffleOptions.TraceRewritesFilterFromCost != null) {
+            if (filterByKind(this, TruffleOptions.TraceRewritesFilterFromCost)) {
                 return;
             }
         }
 
-        if (TruffleOptions.TraceRewritesFilterToKind != null) {
-            if (filterByKind(to, TruffleOptions.TraceRewritesFilterToKind)) {
+        if (TruffleOptions.TraceRewritesFilterToCost != null) {
+            if (filterByKind(newNode, TruffleOptions.TraceRewritesFilterToCost)) {
                 return;
             }
         }
 
         String filter = TruffleOptions.TraceRewritesFilterClass;
+        Class<? extends Node> from = getClass();
+        Class<? extends Node> to = newNode.getClass();
         if (filter != null && (filterByContainsClassName(from, filter) || filterByContainsClassName(to, filter))) {
             return;
         }
 
         PrintStream out = System.out;
-        out.printf("[truffle]   rewrite %-50s |From %-40s |To %-40s |Reason %s.%n", this.toString(), formatNodeInfo(from), formatNodeInfo(to), reason);
+        out.printf("[truffle]   rewrite %-50s |From %-40s |To %-40s |Reason %s.%n", this.toString(), formatNodeInfo(this), formatNodeInfo(newNode), reason);
     }
 
-    private static String formatNodeInfo(Class<? extends Node> clazz) {
-        NodeInfo nodeInfo = clazz.getAnnotation(NodeInfo.class);
-        String kind = "?";
-        if (nodeInfo != null) {
-            switch (nodeInfo.kind()) {
-                case GENERIC:
-                    kind = "G";
-                    break;
-                case SPECIALIZED:
-                    kind = "S";
-                    break;
-                case UNINITIALIZED:
-                    kind = "U";
-                    break;
-                case POLYMORPHIC:
-                    kind = "P";
-                    break;
-                default:
-                    kind = "?";
-                    break;
-            }
+    private static String formatNodeInfo(Node node) {
+        String cost = "?";
+        switch (node.getCost()) {
+            case NONE:
+                cost = "G";
+                break;
+            case MONOMORPHIC:
+                cost = "M";
+                break;
+            case POLYMORPHIC:
+                cost = "P";
+                break;
+            case MEGAMORPHIC:
+                cost = "G";
+                break;
+            default:
+                cost = "?";
+                break;
         }
-        return kind + " " + clazz.getSimpleName();
+        return cost + " " + node.getClass().getSimpleName();
     }
 
-    private static boolean filterByKind(Class<?> clazz, Kind kind) {
-        NodeInfo info = clazz.getAnnotation(NodeInfo.class);
-        if (info != null) {
-            return info.kind() != kind;
-        }
-        return true;
+    private static boolean filterByKind(Node node, NodeCost cost) {
+        return node.getCost() == cost;
     }
 
     private static boolean filterByContainsClassName(Class<? extends Node> from, String filter) {
@@ -435,4 +483,32 @@
         sb.append("@").append(Integer.toHexString(hashCode()));
         return sb.toString();
     }
+
+    public final void atomic(Runnable closure) {
+        RootNode rootNode = getRootNode();
+        if (rootNode != null) {
+            synchronized (rootNode) {
+                closure.run();
+            }
+        } else {
+            closure.run();
+        }
+    }
+
+    public final <T> T atomic(Callable<T> closure) {
+        try {
+            RootNode rootNode = getRootNode();
+            if (rootNode != null) {
+                synchronized (rootNode) {
+                    return closure.call();
+                }
+            } else {
+                return closure.call();
+            }
+        } catch (RuntimeException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCost.java	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,69 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.nodes;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Represents a rough estimate for the cost of a {@link Node}. This estimate can be used by runtime
+ * systems or guest languages to implement heuristics based on Truffle ASTs.
+ * 
+ * @see Node#getCost()
+ */
+public enum NodeCost {
+
+    /**
+     * This node has literally no costs and should be ignored for heuristics. This is particularly
+     * useful for wrapper and profiling nodes which should not influence the heuristics.
+     */
+    NONE,
+
+    /**
+     * This node has a {@link CompilerDirectives#transferToInterpreter()} or
+     * {@link CompilerDirectives#transferToInterpreterAndInvalidate()} as its first unconditional
+     * statement.
+     */
+    UNINITIALIZED,
+
+    /**
+     * This node represents a specialized monomorphic version of an operation.
+     */
+    MONOMORPHIC,
+
+    /**
+     * This node represents a polymorphic version of an operation. For multiple chained polymorphic
+     * nodes the first may return {@link #MONOMORPHIC} and all addtional nodes should return
+     * {@link #POLYMORPHIC}.
+     */
+    POLYMORPHIC,
+
+    /**
+     * This node represents a megamorphic version of an operation. This value should only be used if
+     * the operation implementation supports monomorphism and polymorphism otherwise
+     * {@link #MONOMORPHIC} should be used instead.
+     */
+    MEGAMORPHIC;
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java	Thu Mar 20 13:50:21 2014 +0100
@@ -40,10 +40,13 @@
      */
     String shortName() default "";
 
-    Kind kind() default Kind.SPECIALIZED;
-
-    public enum Kind {
-        UNINITIALIZED, SPECIALIZED, POLYMORPHIC, GENERIC
-    }
+    /**
+     * Provides a rough estimate for the cost of the annotated {@link Node}. This estimate can be
+     * used by runtime systems or guest languages to implement heuristics based on Truffle ASTs.
+     * 
+     * @see Node#getCost()
+     * @see NodeCost
+     */
+    NodeCost cost() default NodeCost.MONOMORPHIC;
 
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Mar 20 13:50:21 2014 +0100
@@ -34,7 +34,6 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.nodes.Node.Child;
 import com.oracle.truffle.api.nodes.Node.Children;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 
 /**
  * Utility class that manages the special access methods for node instances.
@@ -452,48 +451,6 @@
         return null;
     }
 
-    /**
-     * @deprecated will be removed, exposed Truffle runtime specific functionality.
-     */
-    @Deprecated
-    public static List<CallTarget> findOutermostCallTargets(Node node) {
-        RootNode root = node.getRootNode();
-        if (root == null) {
-            return Collections.emptyList();
-        }
-        List<CallTarget> roots = new ArrayList<>();
-        roots.add(root.getCallTarget());
-        for (CallNode callNode : root.getCachedCallNodes()) {
-            if (callNode.isInlined()) {
-                roots.addAll(findOutermostCallTargets(callNode));
-            }
-        }
-        return roots;
-    }
-
-    /**
-     * @deprecated will be removed, exposed Truffle runtime specific functionality.
-     */
-    @Deprecated
-    public static RootNode findOutermostRootNode(Node node) {
-        Node parent = node;
-        while (parent != null) {
-            if (parent instanceof RootNode) {
-                RootNode root = (RootNode) parent;
-                @SuppressWarnings("deprecation")
-                Node next = root.getParentInlinedCall();
-                if (next != null) {
-                    parent = next;
-                } else {
-                    return root;
-                }
-            } else {
-                parent = parent.getParent();
-            }
-        }
-        return null;
-    }
-
     public static <T> T findParent(Node start, Class<T> clazz) {
         Node parent = start.getParent();
         if (parent == null) {
@@ -614,39 +571,43 @@
     }
 
     public static int countNodes(Node root) {
-        return countNodes(root, null, null, false);
+        return countNodes(root, null, false);
     }
 
-    public static int countNodes(Node root, Class<?> clazz, Kind nodeKind, boolean countInlinedCallNodes) {
-        NodeCountVisitor nodeCount = new NodeCountVisitor(clazz, nodeKind, countInlinedCallNodes);
+    public static int countNodes(Node root, NodeCountFilter filter) {
+        return countNodes(root, filter, false);
+    }
+
+    public static int countNodes(Node root, NodeCountFilter filter, boolean visitInlinedCallNodes) {
+        NodeCountVisitor nodeCount = new NodeCountVisitor(filter, visitInlinedCallNodes);
         root.accept(nodeCount);
         return nodeCount.nodeCount;
     }
 
-    public static int countNodes(Node root, Class<?> clazz, boolean countInlinedCallNodes) {
-        return countNodes(root, clazz, null, countInlinedCallNodes);
+    public interface NodeCountFilter {
+
+        boolean isCounted(Node node);
+
     }
 
     private static final class NodeCountVisitor implements NodeVisitor {
 
-        private final boolean inspectInlinedCalls;
+        private final boolean visitInlinedCallNodes;
         int nodeCount;
-        private final Kind kind;
-        private final Class<?> clazz;
+        private final NodeCountFilter filter;
 
-        private NodeCountVisitor(Class<?> clazz, Kind kind, boolean inspectInlinedCalls) {
-            this.clazz = clazz;
-            this.kind = kind;
-            this.inspectInlinedCalls = inspectInlinedCalls;
+        private NodeCountVisitor(NodeCountFilter filter, boolean visitInlinedCallNodes) {
+            this.filter = filter;
+            this.visitInlinedCallNodes = visitInlinedCallNodes;
         }
 
         @Override
         public boolean visit(Node node) {
-            if ((clazz == null || clazz.isInstance(node)) && (kind == null || isKind(node))) {
+            if (filter == null || filter.isCounted(node)) {
                 nodeCount++;
             }
 
-            if (inspectInlinedCalls && node instanceof CallNode) {
+            if (visitInlinedCallNodes && node instanceof CallNode) {
                 CallNode call = (CallNode) node;
                 if (call.isInlined()) {
                     Node target = ((RootCallTarget) call.getCurrentCallTarget()).getRootNode();
@@ -659,9 +620,6 @@
             return true;
         }
 
-        private boolean isKind(Node n) {
-            return kind == n.getKind();
-        }
     }
 
     public static void printInliningTree(final PrintStream stream, RootNode root) {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -36,7 +36,7 @@
  */
 public abstract class RootNode extends Node {
 
-    private CallTarget callTarget;
+    private RootCallTarget callTarget;
     private final FrameDescriptor frameDescriptor;
 
     /*
@@ -62,36 +62,24 @@
     }
 
     /**
-     * @deprecated Not required anymore. Do not use.
+     * Creates a split {@link RootNode} based on the current {@link RootNode}. This method should
+     * return an AST that was never executed and must not be shared with other {@link RootNode} or
+     * {@link CallTarget} instances. This method is intended to be overridden by a subclass.
+     * 
+     * @return the split {@link RootNode}
      */
-    @Deprecated
-    public RootNode inline() {
-        if (!isInlinable()) {
-            throw new UnsupportedOperationException("Inlining is not enabled.");
-        }
-        return split();
+    public RootNode split() {
+        throw new UnsupportedOperationException();
     }
 
     /**
-     * @deprecated Not required anymore. Do not use.
-     */
-    @Deprecated
-    public int getInlineNodeCount() {
-        return 0;
-    }
-
-    /**
-     * @deprecated Not required anymore. Do not use.
+     * Returns <code>true</code> if this {@link RootNode} can be split. A {@link RootNode} can be
+     * split inside of a {@link CallTarget} that is invoked using a {@link CallNode}. If this method
+     * returns <code>true</code> a proper implementation of {@link #split()} must also be provided.
+     * This method is intended to be overridden by a subclass.
+     * 
+     * @return <code>true</code> if splittable else <code>false</code>.
      */
-    @Deprecated
-    public boolean isInlinable() {
-        return true;
-    }
-
-    public RootNode split() {
-        return NodeUtil.cloneNode(this);
-    }
-
     public boolean isSplittable() {
         return false;
     }
@@ -100,7 +88,7 @@
      * Reports the execution count of a loop that is a child of this node. The optimization
      * heuristics can use the loop count to guide compilation and inlining.
      */
-    public void reportLoopCount(int count) {
+    public final void reportLoopCount(int count) {
         if (getCallTarget() instanceof LoopCountReceiver) {
             ((LoopCountReceiver) getCallTarget()).reportLoopCount(count);
         }
@@ -114,7 +102,7 @@
      */
     public abstract Object execute(VirtualFrame frame);
 
-    public CallTarget getCallTarget() {
+    public final RootCallTarget getCallTarget() {
         return callTarget;
     }
 
@@ -122,17 +110,17 @@
         return frameDescriptor;
     }
 
-    public final void setCallTarget(CallTarget callTarget) {
+    public final void setCallTarget(RootCallTarget callTarget) {
         this.callTarget = callTarget;
     }
 
     /* Internal API. Do not use. */
-    void addCachedCallNode(CallNode callSite) {
+    final void addCachedCallNode(CallNode callSite) {
         this.cachedCallNodes.add(callSite);
     }
 
     /* Internal API. Do not use. */
-    void removeCachedCallNode(CallNode callSite) {
+    final void removeCachedCallNode(CallNode callSite) {
         this.cachedCallNodes.remove(callSite);
     }
 
@@ -148,11 +136,4 @@
         return Collections.unmodifiableSet(cachedCallNodes);
     }
 
-    /**
-     * @deprecated use {@link #getCachedCallNodes()} instead.
-     */
-    @Deprecated
-    public final CallNode getParentInlinedCall() {
-        return cachedCallNodes.isEmpty() ? null : cachedCallNodes.iterator().next();
-    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -62,7 +62,7 @@
      */
     protected void internalAppendProbe(InstrumentationProbeNode newProbeNode) {
         if (next == null) {
-            this.next = adoptChild(newProbeNode);
+            this.next = newProbeNode;
         } else {
             next.internalAppendProbe(newProbeNode);
         }
@@ -75,7 +75,7 @@
             if (oldProbeNode.next == null) {
                 this.next = null;
             } else {
-                this.next = adoptChild(oldProbeNode.next);
+                this.next = oldProbeNode.next;
                 oldProbeNode.next = null;
             }
         } else {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Thu Mar 20 13:50:21 2014 +0100
@@ -52,7 +52,7 @@
     private final DeclaredType childAnnotation;
     private final DeclaredType childrenAnnotation;
     private final DeclaredType nodeInfoAnnotation;
-    private final DeclaredType nodeInfoKind;
+    private final DeclaredType nodeCost;
     private final TypeMirror compilerDirectives;
     private final TypeMirror compilerAsserts;
     private final DeclaredType slowPath;
@@ -75,7 +75,7 @@
         assumption = getRequired(context, Assumption.class);
         invalidAssumption = getRequired(context, InvalidAssumptionException.class);
         nodeInfoAnnotation = getRequired(context, NodeInfo.class);
-        nodeInfoKind = getRequired(context, NodeInfo.Kind.class);
+        nodeCost = getRequired(context, NodeCost.class);
         slowPath = getRequired(context, SlowPath.class);
         sourceSection = getRequired(context, SourceSection.class);
         truffleOptions = getRequired(context, TruffleOptions.class);
@@ -107,8 +107,8 @@
         return false;
     }
 
-    public DeclaredType getNodeInfoKind() {
-        return nodeInfoKind;
+    public DeclaredType getNodeCost() {
+        return nodeCost;
     }
 
     private DeclaredType getRequired(ProcessorContext context, Class clazz) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java	Thu Mar 20 13:50:21 2014 +0100
@@ -267,11 +267,9 @@
         if (parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) {
             write(f.getSimpleName());
             if (init != null) {
-                if (init != null) {
-                    write("(");
-                    init.acceptCodeElementScanner(this, p);
-                    write(")");
-                }
+                write("(");
+                init.acceptCodeElementScanner(this, p);
+                write(")");
             }
         } else {
             Element enclosing = f.getEnclosingElement();
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Thu Mar 20 13:50:21 2014 +0100
@@ -32,7 +32,6 @@
 import javax.lang.model.util.*;
 
 import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.ast.*;
@@ -215,20 +214,23 @@
                 if (method.getModifiers().contains(STATIC)) {
                     builder.type(targetClass.asType());
                 } else {
-                    ActualParameter parameter = null;
+                    ActualParameter firstParameter = null;
                     for (ActualParameter searchParameter : targetMethod.getParameters()) {
                         if (searchParameter.getSpecification().isSignature()) {
-                            parameter = searchParameter;
+                            firstParameter = searchParameter;
                             break;
                         }
                     }
-                    ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName());
-                    assert parameter != null;
+                    if (firstParameter == null) {
+                        throw new AssertionError();
+                    }
+
+                    ActualParameter sourceParameter = sourceMethod.findParameter(firstParameter.getLocalName());
 
                     if (castedValues && sourceParameter != null) {
-                        builder.string(valueName(sourceParameter, parameter));
+                        builder.string(valueName(sourceParameter, firstParameter));
                     } else {
-                        builder.string(valueName(parameter));
+                        builder.string(valueName(firstParameter));
                     }
                 }
             }
@@ -929,7 +931,7 @@
                     CodeExecutableElement setter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(void.class), "setNext0");
                     setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0"));
                     CodeTreeBuilder builder = setter.createBuilder();
-                    builder.statement("this.next0 = adoptChild(next0)");
+                    builder.statement("this.next0 = insert(next0)");
                     clazz.add(setter);
 
                     CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization());
@@ -954,28 +956,28 @@
                 clazz.add(createGenericExecute(node, rootGroup));
             }
 
-            clazz.add(createGetKind(node, null, Kind.SPECIALIZED));
+            clazz.add(createGetCost(node, null, NodeCost.MONOMORPHIC));
         }
 
         protected boolean needsInvokeCopyConstructorMethod() {
             return getModel().getNode().isPolymorphic();
         }
 
-        protected CodeExecutableElement createGetKind(NodeData node, SpecializationData specialization, Kind kind) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getNodeInfoKind(), "getKind");
-
-            TypeMirror nodeInfoKind = context.getTruffleTypes().getNodeInfoKind();
+        protected CodeExecutableElement createGetCost(NodeData node, SpecializationData specialization, NodeCost cost) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getNodeCost(), "getCost");
+
+            TypeMirror nodeInfoKind = context.getTruffleTypes().getNodeCost();
 
             CodeTreeBuilder builder = method.createBuilder();
             if (node.isPolymorphic() && specialization == null) {
                 // assume next0 exists
-                builder.startIf().string("next0 != null && next0.getKind() == ").staticReference(nodeInfoKind, "SPECIALIZED").end();
+                builder.startIf().string("next0 != null && next0.getCost() != ").staticReference(nodeInfoKind, "UNINITIALIZED").end();
                 builder.startBlock();
                 builder.startReturn().staticReference(nodeInfoKind, "POLYMORPHIC").end();
                 builder.end();
             }
 
-            builder.startReturn().staticReference(nodeInfoKind, kind.name()).end();
+            builder.startReturn().staticReference(nodeInfoKind, cost.name()).end();
             return method;
         }
 
@@ -1208,7 +1210,6 @@
                 String fieldName = var.getSimpleName().toString();
 
                 CodeTree init = createStaticCast(builder, child, fieldName);
-                init = createAdoptChild(builder, var.asType(), init);
 
                 builder.string("this.").string(fieldName).string(" = ").tree(init);
                 builder.end();
@@ -1227,18 +1228,6 @@
             return CodeTreeBuilder.singleString(fieldName);
         }
 
-        private CodeTree createAdoptChild(CodeTreeBuilder parent, TypeMirror type, CodeTree value) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (Utils.isAssignable(getContext(), type, getContext().getTruffleTypes().getNode())) {
-                builder.string("adoptChild(").tree(value).string(")");
-            } else if (Utils.isAssignable(getContext(), type, getContext().getTruffleTypes().getNodeArray())) {
-                builder.string("adoptChildren(").tree(value).string(")");
-            } else {
-                builder.tree(value);
-            }
-            return builder.getRoot();
-        }
-
         private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor, ExecutableElement sourceSectionConstructor) {
             CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
             CodeTreeBuilder builder = method.createBuilder();
@@ -1259,7 +1248,7 @@
                 if (Utils.isAssignable(getContext(), varType, getContext().getTruffleTypes().getNodeArray())) {
                     copyAccess += ".clone()";
                 }
-                CodeTree init = createAdoptChild(builder, varType, CodeTreeBuilder.singleString(copyAccess));
+                CodeTree init = CodeTreeBuilder.singleString(copyAccess);
                 builder.startStatement().string("this.").string(varName).string(" = ").tree(init).end();
             }
 
@@ -2476,7 +2465,7 @@
             }
             CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false);
 
-            clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC));
+            clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.NONE));
 
             for (ActualParameter polymorphParameter : polymorph.getSignatureParameters()) {
                 if (!polymorphParameter.getTypeSystemType().isGeneric()) {
@@ -2523,7 +2512,7 @@
             }
 
             createCachedExecuteMethods(specialization);
-            clazz.add(createGetKind(specialization.getNode(), specialization, Kind.SPECIALIZED));
+            clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.NONE));
         }
 
         private ExecutableElement createUpdateType(ActualParameter parameter) {
@@ -2563,34 +2552,34 @@
             }
             CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
 
-            Kind kind;
+            NodeCost cost;
             if (specialization.isGeneric()) {
-                kind = Kind.GENERIC;
+                cost = NodeCost.MEGAMORPHIC;
             } else if (specialization.isUninitialized()) {
-                kind = Kind.UNINITIALIZED;
+                cost = NodeCost.UNINITIALIZED;
             } else if (specialization.isPolymorphic()) {
-                kind = Kind.POLYMORPHIC;
+                cost = NodeCost.NONE;
             } else if (specialization.isSpecialized()) {
-                kind = Kind.SPECIALIZED;
+                cost = NodeCost.MONOMORPHIC;
             } else {
                 throw new AssertionError();
             }
-            clazz.getAnnotationMirrors().add(createNodeInfo(node, kind));
+            clazz.getAnnotationMirrors().add(createNodeInfo(node, cost));
 
             return clazz;
         }
 
-        protected CodeAnnotationMirror createNodeInfo(NodeData node, Kind kind) {
+        protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) {
             String shortName = node.getShortName();
             CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
             if (shortName != null) {
                 nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName));
             }
 
-            DeclaredType nodeinfoKind = getContext().getTruffleTypes().getNodeInfoKind();
-            VariableElement varKind = Utils.findVariableElement(nodeinfoKind, kind.name());
-
-            nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("kind"), new CodeAnnotationValue(varKind));
+            DeclaredType nodeinfoCost = getContext().getTruffleTypes().getNodeCost();
+            VariableElement varKind = Utils.findVariableElement(nodeinfoCost, cost.name());
+
+            nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("cost"), new CodeAnnotationValue(varKind));
             return nodeInfoMirror;
         }
 
@@ -2609,9 +2598,9 @@
             }
 
             if (specialization.isGeneric()) {
-                clazz.add(createGetKind(specialization.getNode(), specialization, Kind.GENERIC));
+                clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.MEGAMORPHIC));
             } else if (specialization.isUninitialized()) {
-                clazz.add(createGetKind(specialization.getNode(), specialization, Kind.UNINITIALIZED));
+                clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.UNINITIALIZED));
             }
         }
 
@@ -2633,13 +2622,16 @@
                 }
 
                 CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor);
+                if (superConstructor == null) {
+                    continue;
+                }
                 CodeTree body = superConstructor.getBodyTree();
                 CodeTreeBuilder builder = superConstructor.createBuilder();
                 builder.tree(body);
 
                 if (node.isPolymorphic()) {
                     if (specialization.isSpecialized() || specialization.isPolymorphic()) {
-                        builder.statement("this.next0 = adoptChild(copy.next0)");
+                        builder.statement("this.next0 = copy.next0");
                     }
                 }
                 if (superConstructor != null) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -52,7 +52,7 @@
         super(null, frameDescriptor);
         /* Deep copy the body before any specialization occurs during execution. */
         this.uninitializedBodyNode = NodeUtil.cloneNode(bodyNode);
-        this.bodyNode = adoptChild(bodyNode);
+        this.bodyNode = bodyNode;
         this.name = name;
     }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -53,9 +53,9 @@
 
     protected SLDirectDispatchNode(SLAbstractDispatchNode next, SLFunction cachedFunction) {
         this.cachedFunction = cachedFunction;
-        this.callCachedTargetNode = adoptChild(Truffle.getRuntime().createCallNode(cachedFunction.getCallTarget()));
+        this.callCachedTargetNode = Truffle.getRuntime().createCallNode(cachedFunction.getCallTarget());
         this.cachedTargetStable = cachedFunction.getCallTargetStable();
-        this.nextNode = adoptChild(next);
+        this.nextNode = next;
     }
 
     /**
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -48,9 +48,9 @@
     @Child protected SLAbstractDispatchNode dispatchNode;
 
     private SLInvokeNode(SLExpressionNode functionNode, SLExpressionNode[] argumentNodes, SLAbstractDispatchNode dispatchNode) {
-        this.functionNode = adoptChild(functionNode);
-        this.argumentNodes = adoptChildren(argumentNodes);
-        this.dispatchNode = adoptChild(dispatchNode);
+        this.functionNode = functionNode;
+        this.argumentNodes = argumentNodes;
+        this.dispatchNode = dispatchNode;
     }
 
     @Override
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -45,7 +45,7 @@
          * It is a Truffle requirement to call adoptChildren(), which performs all the necessary
          * steps to add the new children to the node tree.
          */
-        this.bodyNodes = adoptChildren(bodyNodes);
+        this.bodyNodes = bodyNodes;
     }
 
     /**
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -54,7 +54,7 @@
          * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps
          * to add the new child to the node tree.
          */
-        this.bodyNode = adoptChild(bodyNode);
+        this.bodyNode = bodyNode;
     }
 
     @Override
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -57,9 +57,9 @@
          * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps
          * to add the new child to the node tree.
          */
-        this.conditionNode = adoptChild(conditionNode);
-        this.thenPartNode = adoptChild(thenPartNode);
-        this.elsePartNode = adoptChild(elsePartNode);
+        this.conditionNode = conditionNode;
+        this.thenPartNode = thenPartNode;
+        this.elsePartNode = elsePartNode;
     }
 
     @Override
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -40,7 +40,7 @@
     @Child private SLExpressionNode valueNode;
 
     public SLReturnNode(SLExpressionNode valueNode) {
-        this.valueNode = adoptChild(valueNode);
+        this.valueNode = valueNode;
     }
 
     @Override
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -55,8 +55,8 @@
          * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps
          * to add the new child to the node tree.
          */
-        this.conditionNode = adoptChild(conditionNode);
-        this.bodyNode = adoptChild(bodyNode);
+        this.conditionNode = conditionNode;
+        this.bodyNode = bodyNode;
     }
 
     @Override
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/demo/SLAddWithoutSpecializationNode.java	Wed Mar 19 19:02:29 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/demo/SLAddWithoutSpecializationNode.java	Thu Mar 20 13:50:21 2014 +0100
@@ -42,8 +42,8 @@
     @Child private SLExpressionNode rightNode;
 
     public SLAddWithoutSpecializationNode(SLExpressionNode leftNode, SLExpressionNode rightNode) {
-        this.leftNode = adoptChild(leftNode);
-        this.rightNode = adoptChild(rightNode);
+        this.leftNode = leftNode;
+        this.rightNode = rightNode;
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/findbugsExcludeFilter.xml	Thu Mar 20 13:50:21 2014 +0100
@@ -0,0 +1,41 @@
+<FindBugsFilter>
+
+  <Match>
+    <Class name="com.oracle.graal.hotspot.CompilationTask" />
+    <Method name="run" />
+    <Bug pattern="NN_NAKED_NOTIFY" />
+  </Match>
+
+  <!-- justification = "concurrent abstraction calls are in synchronized block" -->
+  <Match>
+    <Class name="com.oracle.graal.hotspot.debug.BenchmarkCounters" />
+    <Method name="getIndex" />
+    <Bug pattern="AT_OPERATION_SEQUENCE_ON_CONCURRENT_ABSTRACTION" />
+  </Match>
+
+  <!-- justification = "counters are only used for statistics" -->
+  <Match>
+    <Class name="com.oracle.graal.hotspot.meta.HotSpotGraphCache" />
+    <Or>
+      <Method name="get" />
+      <Method name="put" />
+      <Method name="removeGraphs" />
+    </Or>
+    <Bug pattern="VO_VOLATILE_INCREMENT" />
+  </Match>
+
+  <!-- justification = "reference equality on the receiver is what we want" -->
+  <Match>
+    <Class name="com.oracle.graal.replacements.StringSubstitutions" />
+    <Method name="equals" />
+    <Bug pattern="ES_COMPARING_PARAMETER_STRING_WITH_EQ" />
+  </Match>
+
+  <!-- justification = "reference equality to test whether string is interned" -->
+  <Match>
+    <Class name="com.oracle.graal.hotspot.phases.AheadOfTimeVerificationPhase" />
+    <Method name="isInternedString" />
+    <Bug pattern="ES_COMPARING_STRINGS_WITH_EQ" />
+  </Match>
+
+</FindBugsFilter>
--- a/mx/mx_graal.py	Wed Mar 19 19:02:29 2014 +0100
+++ b/mx/mx_graal.py	Thu Mar 20 13:50:21 2014 +0100
@@ -83,6 +83,12 @@
 
 JDK_UNIX_PERMISSIONS = 0755
 
+def isVMSupported(vm):
+    if 'client' in vm and len(platform.mac_ver()[0]) != 0:
+        # Client VM not supported: java launcher on Mac OS X translates '-client' to '-server'
+        return False
+    return True
+
 def _get_vm():
     """
     Gets the configured VM, presenting a dialogue if there is no currently configured VM.
@@ -569,6 +575,10 @@
                 mx.log('only product build of original VM exists')
             continue
 
+        if not isVMSupported(vm):
+            mx.log('The ' + vm + ' VM is not supported on this platform - skipping')
+            continue
+
         vmDir = join(_vmLibDirInJdk(jdk), vm)
         if not exists(vmDir):
             if mx.get_os() != 'windows':
@@ -718,8 +728,8 @@
     if vm is None:
         vm = _get_vm()
 
-    if 'client' in vm and len(platform.mac_ver()[0]) != 0:
-        mx.abort("Client VM not supported: java launcher on Mac OS X translates '-client' to '-server'")
+    if not isVMSupported(vm):
+        mx.abort('The ' + vm + ' is not supported on this platform')
 
     if cwd is None:
         cwd = _vm_cwd
@@ -927,6 +937,10 @@
 
     allStart = time.time()
     for v in vms:
+        if not isVMSupported(v):
+            mx.log('The ' + v + ' VM is not supported on this platform - skipping')
+            continue
+
         for vmbuild in builds:
             if v == 'original' and vmbuild != 'product':
                 continue
@@ -1043,6 +1057,9 @@
 
         for vmbuild in ['product', 'fastdebug']:
             for theVm in ['client', 'server']:
+                if not isVMSupported(theVm):
+                    mx.log('The' + theVm + ' VM is not supported on this platform')
+                    continue
                 with VM(theVm, vmbuild):
                     t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild)
                     dacapo(['pmd'])
@@ -1175,7 +1192,7 @@
         env = os.environ
         proxy = os.environ.get('http_proxy')
         if not (proxy is None) and len(proxy) > 0:
-            if proxy.contains('://'):
+            if '://' in proxy:
                 # Remove the http:// prefix (or any other protocol prefix)
                 proxy = proxy.split('://', 1)[1]
             # Separate proxy server name and port number
@@ -1638,6 +1655,38 @@
     valueMap = parser.parse(output.getvalue())
     return valueMap
 
+def findbugs(args):
+    '''run FindBugs against non-test Java projects'''
+    findBugsHome = mx.get_env('FINDBUGS_HOME', None)
+    if findBugsHome:
+        findbugsJar = join(findBugsHome, 'lib', 'findbugs.jar')
+    else:
+        findbugsLib = join(_graal_home, 'lib', 'findbugs-3.0.0')
+        if not exists(findbugsLib):
+            tmp = tempfile.mkdtemp(prefix='findbugs-download-tmp', dir=_graal_home)
+            try:
+                findbugsDist = join(tmp, 'findbugs.zip')
+                mx.download(findbugsDist, ['http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0-dev-20131204-e3cbbd5.zip'])
+                with zipfile.ZipFile(findbugsDist) as zf:
+                    candidates = [e for e in zf.namelist() if e.endswith('/lib/findbugs.jar')]
+                    assert len(candidates) == 1, candidates
+                    libDirInZip = os.path.dirname(candidates[0])
+                    zf.extractall(tmp)
+                shutil.copytree(join(tmp, libDirInZip), findbugsLib)
+            finally:
+                shutil.rmtree(tmp)
+        findbugsJar = join(findbugsLib, 'findbugs.jar')
+    assert exists(findbugsJar)
+    nonTestProjects = [p for p in mx.projects() if not p.name.endswith('.test') and not p.name.endswith('.jtt')]
+    outputDirs = [p.output_dir() for p in nonTestProjects]
+    findbugsResults = join(_graal_home, 'findbugs.results')
+    exitcode = mx.run_java(['-jar', findbugsJar, '-textui', '-low', '-maxRank', '15', '-exclude', join(_graal_home, 'graal', 'findbugsExcludeFilter.xml'),
+                 '-auxclasspath', mx.classpath([p.name for p in nonTestProjects]), '-output', findbugsResults, '-progress', '-exitcode'] + args + outputDirs, nonZeroIsFatal=False)
+    if exitcode != 0:
+        with open(findbugsResults) as fp:
+            mx.log(fp.read())
+    os.unlink(findbugsResults)
+    return exitcode
 
 def mx_init(suite):
     commands = {
@@ -1646,6 +1695,7 @@
         'buildvms': [buildvms, '[-options]'],
         'c1visualizer' : [c1visualizer, ''],
         'clean': [clean, ''],
+        'findbugs': [findbugs, ''],
         'generateZshCompletion' : [generateZshCompletion, ''],
         'hsdis': [hsdis, '[att]'],
         'hcfdis': [hcfdis, ''],
--- a/mx/projects	Wed Mar 19 19:02:29 2014 +0100
+++ b/mx/projects	Thu Mar 20 13:50:21 2014 +0100
@@ -13,9 +13,6 @@
 library@CHECKSTYLE@path=lib/checkstyle-5.5-all.jar
 library@CHECKSTYLE@urls=jar:http://sourceforge.net/projects/checkstyle/files/checkstyle/5.5/checkstyle-5.5-bin.zip/download!/checkstyle-5.5/checkstyle-5.5-all.jar
 
-library@FINDBUGS@path=lib/findbugs-3.0.0-dev-20131204-e3cbbd5.jar
-library@FINDBUGS@urls=jar:http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0-dev-20131204-e3cbbd5.zip/download!/findbugs-3.0.0-dev-20131204-e3cbbd5/lib/findbugs.jar
-
 library@DACAPO@path=lib/dacapo-9.12-bach.jar
 library@DACAPO@urls=http://softlayer.dl.sourceforge.net/project/dacapobench/9.12-bach/dacapo-9.12-bach.jar
 
@@ -41,6 +38,10 @@
 library@OKRA_WITH_SIM@sourcePath=lib/okra-1.8-with-sim-src.jar
 library@OKRA_WITH_SIM@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-with-sim-src.jar
 
+library@JAVA_ALLOCATION_INSTRUMENTER@path=lib/java-allocation-instrumenter.jar
+library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter.jar
+library@JAVA_ALLOCATION_INSTRUMENTER@sha1=1cd4073f57d7d461a53b0ddc1ea4ee2aa0c60e66
+
 distribution@GRAAL@path=graal.jar
 distribution@GRAAL@dependencies=\
 com.oracle.graal.hotspot.amd64,\
@@ -498,7 +499,7 @@
 # graal.java.decompiler.test
 project@com.oracle.graal.java.decompiler.test@subDir=graal
 project@com.oracle.graal.java.decompiler.test@sourceDirs=src
-project@com.oracle.graal.java.decompiler.test@dependencies=com.oracle.graal.printer,com.oracle.graal.runtime
+project@com.oracle.graal.java.decompiler.test@dependencies=JUNIT,com.oracle.graal.printer,com.oracle.graal.runtime
 project@com.oracle.graal.java.decompiler.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.java.decompiler.test@javaCompliance=1.7
 project@com.oracle.graal.java.decompiler.test@workingSets=Graal,Test
@@ -522,7 +523,7 @@
 # graal.compiler.test
 project@com.oracle.graal.compiler.test@subDir=graal
 project@com.oracle.graal.compiler.test@sourceDirs=src
-project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.printer,com.oracle.graal.runtime,com.oracle.graal.baseline
+project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.printer,com.oracle.graal.runtime,com.oracle.graal.baseline,JAVA_ALLOCATION_INSTRUMENTER
 project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.test@javaCompliance=1.7
 project@com.oracle.graal.compiler.test@workingSets=Graal,Test
--- a/mxtool/mx.py	Wed Mar 19 19:02:29 2014 +0100
+++ b/mxtool/mx.py	Thu Mar 20 13:50:21 2014 +0100
@@ -40,6 +40,7 @@
 import xml.parsers.expat
 import shutil, re, xml.dom.minidom
 import pipes
+import difflib
 from collections import Callable
 from threading import Thread
 from argparse import ArgumentParser, REMAINDER
@@ -1894,10 +1895,13 @@
         abort('Could not find Eclipse executable. Use -e option or ensure ECLIPSE_EXE environment variable is set.')
 
     # Maybe an Eclipse installation dir was specified - look for the executable in it
-    if join(args.eclipse_exe, exe_suffix('eclipse')):
+    if isdir(args.eclipse_exe):
         args.eclipse_exe = join(args.eclipse_exe, exe_suffix('eclipse'))
-
-    if not os.path.isfile(args.eclipse_exe) or not os.access(args.eclipse_exe, os.X_OK):
+        warn("The eclipse-exe was a directory, now using " + args.eclipse_exe)
+
+    if not os.path.isfile(args.eclipse_exe):
+        abort('File does not exist: ' + args.eclipse_exe)
+    if not os.access(args.eclipse_exe, os.X_OK):
         abort('Not an executable file: ' + args.eclipse_exe)
 
     eclipseinit([], buildProcessorJars=False)
@@ -1927,6 +1931,7 @@
             with open(self.path) as fp:
                 content = fp.read()
                 if self.content != content:
+                    self.diff = difflib.unified_diff(self.content.splitlines(1), content.splitlines(1))
                     self.content = content
                     return True
             os.utime(self.path, self.times)
@@ -1964,6 +1969,7 @@
                 modified.append(fi)
 
     log('{0} files were modified'.format(len(modified)))
+
     if len(modified) != 0:
         arcbase = _primary_suite.dir
         if args.backup:
@@ -1972,6 +1978,8 @@
         for fi in modified:
             name = os.path.relpath(fi.path, arcbase)
             log(' - {0}'.format(name))
+            log('Changes:')
+            log(''.join(fi.diff))
             if args.backup:
                 arcname = name.replace(os.sep, '/')
                 zf.writestr(arcname, fi.content)
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Thu Mar 20 13:50:21 2014 +0100
@@ -41,55 +41,32 @@
   }
 }
 
-inline void CodeInstaller::pd_site_DataPatch(int pc_offset, oop site) {
-  oop inlineData = CompilationResult_DataPatch::inlineData(site);
-  address pc = _instructions->start() + pc_offset;
+inline void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) {
+  if (OopData::compressed(obj)) {
+    fatal("unimplemented: narrow oop relocation");
+  } else {
+    address pc = _instructions->start() + pc_offset;
+    Handle obj = OopData::object(data);
+    jobject value = JNIHandles::make_local(obj());
 
-  if (inlineData != NULL) {
-    oop kind = Constant::kind(inlineData);
-    char typeChar = Kind::typeChar(kind);
+    NativeMovConstReg* move = nativeMovConstReg_at(pc);
+    move->set_data((intptr_t) value);
 
-    switch (typeChar) {
-      case 'z':
-      case 'b':
-      case 's':
-      case 'c':
-      case 'i':
-        fatal("int-sized values not expected in DataPatch");
-        break;
-      case 'f':
-      case 'j':
-      case 'd': {
-        NativeMovConstReg* move = nativeMovConstReg_at(pc);
-        uint64_t value = Constant::primitive(inlineData);
-        move->set_data(value);
-        break;
-      }
-      case 'a': {
-        NativeMovConstReg* move = nativeMovConstReg_at(pc);
-        Handle obj = Constant::object(inlineData);
-        jobject value = JNIHandles::make_local(obj());
-        move->set_data((intptr_t) value);
+    // We need two relocations:  one on the sethi and one on the add.
+    int oop_index = _oop_recorder->find_index(value);
+    RelocationHolder rspec = oop_Relocation::spec(oop_index);
+    _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec);
+    _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec);
+  }
+}
 
-        // We need two relocations:  one on the sethi and one on the add.
-        int oop_index = _oop_recorder->find_index(value);
-        RelocationHolder rspec = oop_Relocation::spec(oop_index);
-        _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec);
-        _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec);
-        break;
-      }
-      default:
-        fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar));
-        break;
-    }
-  } else {
-    oop dataRef = CompilationResult_DataPatch::externalData(site);
-    jint offset = HotSpotCompiledCode_HotSpotData::offset(dataRef);
+inline void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) {
+  address pc = _instructions->start() + pc_offset;
+  jint offset = DataSectionReference::offset(data);
 
-    NativeMovRegMem* load = nativeMovRegMem_at(pc);
-    int disp = _constants_size + pc_offset - offset - BytesPerInstWord;
-    load->set_offset(-disp);
-  }
+  NativeMovRegMem* load = nativeMovRegMem_at(pc);
+  int disp = _constants_size + pc_offset - offset - BytesPerInstWord;
+  load->set_offset(-disp);
 }
 
 inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
@@ -121,24 +98,24 @@
   }
 #endif
   switch (_next_call_type) {
-    case MARK_INLINE_INVOKE:
+    case INLINE_INVOKE:
       break;
-    case MARK_INVOKEVIRTUAL:
-    case MARK_INVOKEINTERFACE: {
+    case INVOKEVIRTUAL:
+    case INVOKEINTERFACE: {
       assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
       NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
       call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
       _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc));
       break;
     }
-    case MARK_INVOKESTATIC: {
+    case INVOKESTATIC: {
       assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
       NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
       call->set_destination(SharedRuntime::get_resolve_static_call_stub());
       _instructions->relocate(call->instruction_address(), relocInfo::static_call_type);
       break;
     }
-    case MARK_INVOKESPECIAL: {
+    case INVOKESPECIAL: {
       assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
       NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
       call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
@@ -153,16 +130,16 @@
 
 inline void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
   switch (mark) {
-    case MARK_POLL_NEAR: {
+    case POLL_NEAR: {
       fatal("unimplemented");
     }
-    case MARK_POLL_FAR:
+    case POLL_FAR:
       _instructions->relocate(pc, relocInfo::poll_type);
       break;
-    case MARK_POLL_RETURN_NEAR: {
+    case POLL_RETURN_NEAR: {
       fatal("unimplemented");
     }
-    case MARK_POLL_RETURN_FAR:
+    case POLL_RETURN_FAR:
       _instructions->relocate(pc, relocInfo::poll_return_type);
       break;
     default:
--- a/src/cpu/x86/vm/graalCodeInstaller_x86.hpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/cpu/x86/vm/graalCodeInstaller_x86.hpp	Thu Mar 20 13:50:21 2014 +0100
@@ -59,68 +59,49 @@
   }
 }
 
-inline void CodeInstaller::pd_site_DataPatch(int pc_offset, oop site) {
-  oop inlineData = CompilationResult_DataPatch::inlineData(site);
+inline bool check_metaspace_data(address pc, oop data) {
+  jlong value = MetaspaceData::value(data);
+  address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
+  if (MetaspaceData::compressed(data)) {
+    assert(*((jint*) operand) == value, err_msg("wrong compressed metaspace pointer: %p != %p", *((jint*) operand), value));
+  } else {
+    assert(*((jlong*) operand) == value, err_msg("wrong metaspace pointer: %p != %p", *((jlong*) operand), value));
+  }
+  return true;
+}
+
+inline void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) {
   address pc = _instructions->start() + pc_offset;
 
-  if (inlineData != NULL) {
-    oop kind = Constant::kind(inlineData);
-    char typeChar = Kind::typeChar(kind);
-
-    switch (typeChar) {
-      case 'z':
-      case 'b':
-      case 's':
-      case 'c':
-      case 'i':
-        fatal("int-sized values not expected in DataPatch");
-        break;
-      case 'n': {
-        address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
-        Handle obj = Constant::object(inlineData);
+  Handle obj = OopData::object(data);
+  jobject value = JNIHandles::make_local(obj());
+  if (OopData::compressed(data)) {
+    address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
+    int oop_index = _oop_recorder->find_index(value);
+    _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand);
+    TRACE_graal_3("relocating (narrow oop constant) at %p/%p", pc, operand);
+  } else {
+    address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
+    *((jobject*) operand) = value;
+    _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+    TRACE_graal_3("relocating (oop constant) at %p/%p", pc, operand);
+  }
+}
 
-        jobject value = JNIHandles::make_local(obj());
-        int oop_index = _oop_recorder->find_index(value);
-        _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand);
-        TRACE_graal_3("relocating (narrow oop constant) at %p/%p", pc, operand);
-        break;
-      }
-      case 'f':
-      case 'j':
-      case 'd':
-      case '*': {
-        address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
-        *((jlong*) operand) = Constant::primitive(inlineData);
-        break;
-      }
-      case 'a': {
-        address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
-        Handle obj = Constant::object(inlineData);
+inline void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) {
+  address pc = _instructions->start() + pc_offset;
+  jint offset = DataSectionReference::offset(data);
 
-        jobject value = JNIHandles::make_local(obj());
-        *((jobject*) operand) = value;
-        _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
-        TRACE_graal_3("relocating (oop constant) at %p/%p", pc, operand);
-        break;
-      }
-      default:
-        fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar));
-        break;
-    }
-  } else {
-    oop dataRef = CompilationResult_DataPatch::externalData(site);
-    jint offset = HotSpotCompiledCode_HotSpotData::offset(dataRef);
-    address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
-    address next_instruction = Assembler::locate_next_instruction(pc);
-    address dest = _constants->start() + offset;
+  address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
+  address next_instruction = Assembler::locate_next_instruction(pc);
+  address dest = _constants->start() + offset;
 
-    long disp = dest - next_instruction;
-    assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
-    *((jint*) operand) = (jint) disp;
+  long disp = dest - next_instruction;
+  assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+  *((jint*) operand) = (jint) disp;
 
-    _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
-    TRACE_graal_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, offset);
-  }
+  _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
+  TRACE_graal_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, offset);
 }
 
 inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
@@ -170,10 +151,10 @@
   }
 #endif
   switch (_next_call_type) {
-    case MARK_INLINE_INVOKE:
+    case INLINE_INVOKE:
       break;
-    case MARK_INVOKEVIRTUAL:
-    case MARK_INVOKEINTERFACE: {
+    case INVOKEVIRTUAL:
+    case INVOKEINTERFACE: {
       assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
 
       NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
@@ -183,7 +164,7 @@
                                              Assembler::call32_operand);
       break;
     }
-    case MARK_INVOKESTATIC: {
+    case INVOKESTATIC: {
       assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
 
       NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
@@ -192,7 +173,7 @@
                                              relocInfo::static_call_type, Assembler::call32_operand);
       break;
     }
-    case MARK_INVOKESPECIAL: {
+    case INVOKESPECIAL: {
       assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
       NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
       call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
@@ -216,24 +197,24 @@
 
 inline void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
   switch (mark) {
-    case MARK_POLL_NEAR: {
+    case POLL_NEAR: {
       relocate_poll_near(pc);
       _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand);
       break;
     }
-    case MARK_POLL_FAR:
+    case POLL_FAR:
       // This is a load from a register so there is no relocatable operand.
       // We just have to ensure that the format is not disp32_operand
       // so that poll_Relocation::fix_relocation_after_move does the right
       // thing (i.e. ignores this relocation record)
       _instructions->relocate(pc, relocInfo::poll_type, Assembler::imm_operand);
       break;
-    case MARK_POLL_RETURN_NEAR: {
+    case POLL_RETURN_NEAR: {
       relocate_poll_near(pc);
       _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::disp32_operand);
       break;
     }
-    case MARK_POLL_RETURN_FAR:
+    case POLL_RETURN_FAR:
       // see comment above for MARK_POLL_FAR
       _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand);
       break;
--- a/src/share/vm/classfile/systemDictionary.hpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/classfile/systemDictionary.hpp	Thu Mar 20 13:50:21 2014 +0100
@@ -187,12 +187,15 @@
   do_klass(BitSet_klass,                          java_util_BitSet,                                             Opt) \
   /* graal.hotspot */                                                                                                \
   do_klass(HotSpotCompiledCode_klass,             com_oracle_graal_hotspot_HotSpotCompiledCode,                 Opt) \
-  do_klass(HotSpotCompiledCode_HotSpotData_klass, com_oracle_graal_hotspot_HotSpotCompiledCode_HotSpotData,     Opt) \
-  do_klass(HotSpotCompiledCode_DataSection_klass, com_oracle_graal_hotspot_HotSpotCompiledCode_DataSection,     Opt) \
   do_klass(HotSpotCompiledCode_Comment_klass,     com_oracle_graal_hotspot_HotSpotCompiledCode_Comment,         Opt) \
   do_klass(HotSpotCompiledNmethod_klass,          com_oracle_graal_hotspot_HotSpotCompiledNmethod,              Opt) \
   do_klass(HotSpotCompiledRuntimeStub_klass,      com_oracle_graal_hotspot_HotSpotCompiledRuntimeStub,          Opt) \
   do_klass(HotSpotForeignCallLinkage_klass,       com_oracle_graal_hotspot_HotSpotForeignCallLinkage,           Opt) \
+  do_klass(HotSpotReferenceMap_klass,             com_oracle_graal_hotspot_HotSpotReferenceMap,                 Opt) \
+  do_klass(DataSection_klass,                     com_oracle_graal_hotspot_data_DataSection,                    Opt) \
+  do_klass(DataSectionReference_klass,            com_oracle_graal_hotspot_data_DataSectionReference,           Opt) \
+  do_klass(MetaspaceData_klass,                   com_oracle_graal_hotspot_data_MetaspaceData,                  Opt) \
+  do_klass(OopData_klass,                         com_oracle_graal_hotspot_data_OopData,                        Opt) \
   do_klass(HotSpotCodeInfo_klass,                 com_oracle_graal_hotspot_meta_HotSpotCodeInfo,                Opt) \
   do_klass(HotSpotInstalledCode_klass,            com_oracle_graal_hotspot_meta_HotSpotInstalledCode,           Opt) \
   do_klass(HotSpotNmethod_klass,                  com_oracle_graal_hotspot_meta_HotSpotNmethod,                 Opt) \
@@ -210,7 +213,6 @@
   do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_code_Assumptions_CallSiteTargetValue,    Opt) \
   do_klass(BytecodePosition_klass,                com_oracle_graal_api_code_BytecodePosition,                   Opt) \
   do_klass(DebugInfo_klass,                       com_oracle_graal_api_code_DebugInfo,                          Opt) \
-  do_klass(ReferenceMap_klass,                    com_oracle_graal_api_code_ReferenceMap,                       Opt) \
   do_klass(RegisterSaveLayout_klass,              com_oracle_graal_api_code_RegisterSaveLayout,                 Opt) \
   do_klass(BytecodeFrame_klass,                   com_oracle_graal_api_code_BytecodeFrame,                      Opt) \
   do_klass(CompilationResult_klass,               com_oracle_graal_api_code_CompilationResult,                  Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Mar 20 13:50:21 2014 +0100
@@ -296,14 +296,17 @@
   template(com_oracle_graal_hotspot_HotSpotKlassOop,                 "com/oracle/graal/hotspot/HotSpotKlassOop")                      \
   template(com_oracle_graal_hotspot_HotSpotOptions,                  "com/oracle/graal/hotspot/HotSpotOptions")                       \
   template(com_oracle_graal_hotspot_HotSpotCompiledCode,             "com/oracle/graal/hotspot/HotSpotCompiledCode")                  \
-  template(com_oracle_graal_hotspot_HotSpotCompiledCode_HotSpotData, "com/oracle/graal/hotspot/HotSpotCompiledCode$HotSpotData")      \
-  template(com_oracle_graal_hotspot_HotSpotCompiledCode_DataSection, "com/oracle/graal/hotspot/HotSpotCompiledCode$DataSection")      \
   template(com_oracle_graal_hotspot_HotSpotCompiledCode_Comment,     "com/oracle/graal/hotspot/HotSpotCompiledCode$Comment")          \
   template(com_oracle_graal_hotspot_HotSpotCompiledNmethod,          "com/oracle/graal/hotspot/HotSpotCompiledNmethod")               \
   template(com_oracle_graal_hotspot_HotSpotCompiledRuntimeStub,      "com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub")           \
   template(com_oracle_graal_hotspot_HotSpotForeignCallLinkage,       "com/oracle/graal/hotspot/HotSpotForeignCallLinkage")            \
+  template(com_oracle_graal_hotspot_HotSpotReferenceMap,             "com/oracle/graal/hotspot/HotSpotReferenceMap")                  \
   template(com_oracle_graal_hotspot_bridge_VMToCompiler,             "com/oracle/graal/hotspot/bridge/VMToCompiler")                  \
   template(com_oracle_graal_hotspot_bridge_CompilerToVMImpl,         "com/oracle/graal/hotspot/bridge/CompilerToVMImpl")              \
+  template(com_oracle_graal_hotspot_data_DataSection,                "com/oracle/graal/hotspot/data/DataSection")                     \
+  template(com_oracle_graal_hotspot_data_DataSectionReference,       "com/oracle/graal/hotspot/data/DataSectionReference")            \
+  template(com_oracle_graal_hotspot_data_MetaspaceData,              "com/oracle/graal/hotspot/data/MetaspaceData")                   \
+  template(com_oracle_graal_hotspot_data_OopData,                    "com/oracle/graal/hotspot/data/OopData")                         \
   template(com_oracle_graal_hotspot_meta_HotSpotCodeInfo,            "com/oracle/graal/hotspot/meta/HotSpotCodeInfo")                 \
   template(com_oracle_graal_hotspot_meta_HotSpotInstalledCode,       "com/oracle/graal/hotspot/meta/HotSpotInstalledCode")            \
   template(com_oracle_graal_hotspot_meta_HotSpotNmethod,             "com/oracle/graal/hotspot/meta/HotSpotNmethod")                  \
@@ -340,7 +343,6 @@
   template(com_oracle_graal_api_code_BytecodeFrame,                  "com/oracle/graal/api/code/BytecodeFrame")                       \
   template(com_oracle_graal_api_code_BytecodePosition,               "com/oracle/graal/api/code/BytecodePosition")                    \
   template(com_oracle_graal_api_code_DebugInfo,                      "com/oracle/graal/api/code/DebugInfo")                           \
-  template(com_oracle_graal_api_code_ReferenceMap,                   "com/oracle/graal/api/code/ReferenceMap")                        \
   template(com_oracle_graal_api_code_Register,                       "com/oracle/graal/api/code/Register")                            \
   template(com_oracle_graal_api_code_RegisterValue,                  "com/oracle/graal/api/code/RegisterValue")                       \
   template(com_oracle_graal_api_code_StackSlot,                      "com/oracle/graal/api/code/StackSlot")                           \
--- a/src/share/vm/code/nmethod.cpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/code/nmethod.cpp	Thu Mar 20 13:50:21 2014 +0100
@@ -1025,6 +1025,7 @@
 void nmethod::print_on(outputStream* st, const char* msg) const {
   if (st != NULL) {
     ttyLocker ttyl;
+    if (CIPrintCompilerName) st->print("%s:", compiler()->name());
     if (WizardMode) {
       CompileTask::print_compilation(st, this, msg, /*short_form:*/ true);
       st->print_cr(" (" INTPTR_FORMAT ")", this);
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Thu Mar 20 13:50:21 2014 +0100
@@ -91,8 +91,8 @@
 static OopMap* create_oop_map(jint total_frame_size, jint parameter_count, oop debug_info) {
   OopMap* map = new OopMap(total_frame_size, parameter_count);
   oop reference_map = DebugInfo::referenceMap(debug_info);
-  oop register_map = ReferenceMap::registerRefMap(reference_map);
-  oop frame_map = ReferenceMap::frameRefMap(reference_map);
+  oop register_map = HotSpotReferenceMap::registerRefMap(reference_map);
+  oop frame_map = HotSpotReferenceMap::frameRefMap(reference_map);
   oop callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info);
 
   if (register_map != NULL) {
@@ -157,6 +157,27 @@
   return map;
 }
 
+static void record_metadata_reference(oop obj, jlong prim, bool compressed, OopRecorder* oop_recorder) {
+  if (obj->is_a(HotSpotResolvedObjectType::klass())) {
+    Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaClass(obj));
+    if (compressed) {
+      assert(Klass::decode_klass((narrowKlass) prim) == klass, err_msg("%s @ %p != %p", klass->name()->as_C_string(), klass, prim));
+    } else {
+      assert((Klass*) prim == klass, err_msg("%s @ %p != %p", klass->name()->as_C_string(), klass, prim));
+    }
+    int index = oop_recorder->find_index(klass);
+    TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), klass->name()->as_C_string());
+  } else if (obj->is_a(HotSpotResolvedJavaMethod::klass())) {
+    Method* method = (Method*) (address) HotSpotResolvedJavaMethod::metaspaceMethod(obj);
+    assert(!compressed, err_msg("unexpected compressed method pointer %s @ %p = %p", method->name()->as_C_string(), method, prim));
+    int index = oop_recorder->find_index(method);
+    TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), method->name()->as_C_string());
+  } else {
+    assert(java_lang_String::is_instance(obj),
+        err_msg("unexpected metadata reference (%s) for constant %ld (%p)", obj->klass()->name()->as_C_string(), prim, prim));
+  }
+}
+
 // Records any Metadata values embedded in a Constant (e.g., the value returned by HotSpotResolvedObjectType.klass()).
 static void record_metadata_in_constant(oop constant, OopRecorder* oop_recorder) {
   char kind = Kind::typeChar(Constant::kind(constant));
@@ -165,23 +186,15 @@
     oop obj = Constant::object(constant);
     jlong prim = Constant::primitive(constant);
     if (obj != NULL) {
-      if (obj->is_a(HotSpotResolvedObjectType::klass())) {
-        Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaClass(obj));
-        assert((Klass*) prim == klass, err_msg("%s @ %p != %p", klass->name()->as_C_string(), klass, prim));
-        int index = oop_recorder->find_index(klass);
-        TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), klass->name()->as_C_string());
-      } else if (obj->is_a(HotSpotResolvedJavaMethod::klass())) {
-        Method* method = (Method*) (address) HotSpotResolvedJavaMethod::metaspaceMethod(obj);
-        int index = oop_recorder->find_index(method);
-        TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), method->name()->as_C_string());
-      } else {
-        assert(java_lang_String::is_instance(obj),
-            err_msg("unexpected annotation type (%s) for constant %ld (%p) of kind %c", obj->klass()->name()->as_C_string(), prim, prim, kind));
-      }
+      record_metadata_reference(obj, prim, false, oop_recorder);
     }
   }
 }
 
+static void record_metadata_in_patch(oop data, OopRecorder* oop_recorder) {
+  record_metadata_reference(MetaspaceData::annotation(data), MetaspaceData::value(data), MetaspaceData::compressed(data) != 0, oop_recorder);
+}
+
 ScopeValue* CodeInstaller::get_scope_value(oop value, int total_frame_size, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, OopRecorder* oop_recorder) {
   second = NULL;
   if (value == Value::ILLEGAL()) {
@@ -445,8 +458,8 @@
 
   // Pre-calculate the constants section size.  This is required for PC-relative addressing.
   _dataSection = HotSpotCompiledCode::dataSection(compiled_code);
-  guarantee(HotSpotCompiledCode_DataSection::sectionAlignment(_dataSection) <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
-  arrayOop data = (arrayOop) HotSpotCompiledCode_DataSection::data(_dataSection);
+  guarantee(DataSection::sectionAlignment(_dataSection) <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
+  arrayOop data = (arrayOop) DataSection::data(_dataSection);
   _constants_size = data->length();
   if (_constants_size > 0) {
     _constants_size = align_size_up(_constants_size, _constants->alignment());
@@ -456,7 +469,7 @@
   _comments = (arrayOop) HotSpotCompiledCode::comments(compiled_code);
 #endif
 
-  _next_call_type = MARK_INVOKE_INVALID;
+  _next_call_type = INVOKE_INVALID;
 }
 
 // perform data and call relocation on the CodeBuffer
@@ -482,30 +495,24 @@
 
   // copy the constant data into the newly created CodeBuffer
   address end_data = _constants->start() + _constants_size;
-  arrayOop data = (arrayOop) HotSpotCompiledCode_DataSection::data(_dataSection);
+  arrayOop data = (arrayOop) DataSection::data(_dataSection);
   memcpy(_constants->start(), data->base(T_BYTE), data->length());
   _constants->set_end(end_data);
 
-  objArrayOop patches = (objArrayOop) HotSpotCompiledCode_DataSection::patches(_dataSection);
+  objArrayOop patches = (objArrayOop) DataSection::patches(_dataSection);
   for (int i = 0; i < patches->length(); i++) {
     oop patch = patches->obj_at(i);
-    oop constant = HotSpotCompiledCode_HotSpotData::constant(patch);
-    oop kind = Constant::kind(constant);
-    char typeChar = Kind::typeChar(kind);
-    switch (typeChar) {
-      case 'f':
-      case 'j':
-      case 'd':
-        record_metadata_in_constant(constant, _oop_recorder);
-        break;
-      case 'a':
-        Handle obj = Constant::object(constant);
-        jobject value = JNIHandles::make_local(obj());
-        int oop_index = _oop_recorder->find_index(value);
+    oop data = CompilationResult_DataPatch::data(patch);
+    if (data->is_a(MetaspaceData::klass())) {
+      record_metadata_in_patch(data, _oop_recorder);
+    } else if (data->is_a(OopData::klass())) {
+      Handle obj = OopData::object(data);
+      jobject value = JNIHandles::make_local(obj());
+      int oop_index = _oop_recorder->find_index(value);
 
-        address dest = _constants->start() + HotSpotCompiledCode_HotSpotData::offset(patch);
-        _constants->relocate(dest, oop_Relocation::spec(oop_index));
-        break;
+      address dest = _constants->start() + CompilationResult_Site::pcOffset(patch);
+      assert(!OopData::compressed(data), err_msg("unexpected compressed oop in data section"));
+      _constants->relocate(dest, oop_Relocation::spec(oop_index));
     }
   }
 
@@ -769,7 +776,7 @@
     CodeInstaller::pd_relocate_JavaMethod(hotspot_method, pc_offset);
   }
 
-  _next_call_type = MARK_INVOKE_INVALID;
+  _next_call_type = INVOKE_INVALID;
 
   if (debug_info != NULL) {
     _debug_recorder->end_safepoint(next_pc_offset);
@@ -777,19 +784,16 @@
 }
 
 void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) {
-  oop inlineData = CompilationResult_DataPatch::inlineData(site);
-  if (inlineData != NULL) {
-    oop kind = Constant::kind(inlineData);
-    char typeChar = Kind::typeChar(kind);
-    switch (typeChar) {
-      case 'f':
-      case 'j':
-      case 'd':
-        record_metadata_in_constant(inlineData, _oop_recorder);
-        break;
-    }
+  oop data = CompilationResult_DataPatch::data(site);
+  if (data->is_a(MetaspaceData::klass())) {
+    record_metadata_in_patch(data, _oop_recorder);
+  } else if (data->is_a(OopData::klass())) {
+    pd_patch_OopData(pc_offset, data);
+  } else if (data->is_a(DataSectionReference::klass())) {
+    pd_patch_DataSectionReference(pc_offset, data);
+  } else {
+    fatal("unknown data patch type");
   }
-  CodeInstaller::pd_site_DataPatch(pc_offset, site);
 }
 
 void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) {
@@ -802,33 +806,33 @@
     address pc = _instructions->start() + pc_offset;
 
     switch (id) {
-      case MARK_UNVERIFIED_ENTRY:
+      case UNVERIFIED_ENTRY:
         _offsets.set_value(CodeOffsets::Entry, pc_offset);
         break;
-      case MARK_VERIFIED_ENTRY:
+      case VERIFIED_ENTRY:
         _offsets.set_value(CodeOffsets::Verified_Entry, pc_offset);
         break;
-      case MARK_OSR_ENTRY:
+      case OSR_ENTRY:
         _offsets.set_value(CodeOffsets::OSR_Entry, pc_offset);
         break;
-      case MARK_EXCEPTION_HANDLER_ENTRY:
+      case EXCEPTION_HANDLER_ENTRY:
         _offsets.set_value(CodeOffsets::Exceptions, pc_offset);
         break;
-      case MARK_DEOPT_HANDLER_ENTRY:
+      case DEOPT_HANDLER_ENTRY:
         _offsets.set_value(CodeOffsets::Deopt, pc_offset);
         break;
-      case MARK_INVOKEVIRTUAL:
-      case MARK_INVOKEINTERFACE:
-      case MARK_INLINE_INVOKE:
-      case MARK_INVOKESTATIC:
-      case MARK_INVOKESPECIAL:
+      case INVOKEVIRTUAL:
+      case INVOKEINTERFACE:
+      case INLINE_INVOKE:
+      case INVOKESTATIC:
+      case INVOKESPECIAL:
         _next_call_type = (MarkId) id;
         _invoke_mark_pc = pc;
         break;
-      case MARK_POLL_NEAR:
-      case MARK_POLL_FAR:
-      case MARK_POLL_RETURN_NEAR:
-      case MARK_POLL_RETURN_FAR:
+      case POLL_NEAR:
+      case POLL_FAR:
+      case POLL_RETURN_NEAR:
+      case POLL_RETURN_FAR:
         pd_relocate_poll(pc, id);
         break;
       default:
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Thu Mar 20 13:50:21 2014 +0100
@@ -24,28 +24,30 @@
 #ifndef SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP
 #define SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP
 
+#include "graal/graalEnv.hpp"
+
 /*
  * This class handles the conversion from a InstalledCode to a CodeBlob or an nmethod.
  */
 class CodeInstaller {
+  friend class VMStructs;
 private:
-  // these need to correspond to Marks.java
   enum MarkId {
-    MARK_VERIFIED_ENTRY             = 1,
-    MARK_UNVERIFIED_ENTRY           = 2,
-    MARK_OSR_ENTRY                  = 3,
-    MARK_EXCEPTION_HANDLER_ENTRY    = 4,
-    MARK_DEOPT_HANDLER_ENTRY        = 5,
-    MARK_INVOKEINTERFACE            = 6,
-    MARK_INVOKEVIRTUAL              = 7,
-    MARK_INVOKESTATIC               = 8,
-    MARK_INVOKESPECIAL              = 9,
-    MARK_INLINE_INVOKE              = 10,
-    MARK_POLL_NEAR                  = 11,
-    MARK_POLL_RETURN_NEAR           = 12,
-    MARK_POLL_FAR                   = 13,
-    MARK_POLL_RETURN_FAR            = 14,
-    MARK_INVOKE_INVALID             = -1
+    VERIFIED_ENTRY             = 1,
+    UNVERIFIED_ENTRY           = 2,
+    OSR_ENTRY                  = 3,
+    EXCEPTION_HANDLER_ENTRY    = 4,
+    DEOPT_HANDLER_ENTRY        = 5,
+    INVOKEINTERFACE            = 6,
+    INVOKEVIRTUAL              = 7,
+    INVOKESTATIC               = 8,
+    INVOKESPECIAL              = 9,
+    INLINE_INVOKE              = 10,
+    POLL_NEAR                  = 11,
+    POLL_RETURN_NEAR           = 12,
+    POLL_FAR                   = 13,
+    POLL_RETURN_FAR            = 14,
+    INVOKE_INVALID             = -1
   };
 
   Arena         _arena;
@@ -77,7 +79,8 @@
   ExceptionHandlerTable     _exception_handler_table;
 
   jint pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method);
-  void pd_site_DataPatch(int pc_offset, oop site);
+  void pd_patch_OopData(int pc_offset, oop data);
+  void pd_patch_DataSectionReference(int pc_offset, oop data);
   void pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst);
   void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination);
   void pd_relocate_JavaMethod(oop method, jint pc_offset);
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Mar 20 13:50:21 2014 +0100
@@ -348,11 +348,6 @@
   return CompilerOracle::should_inline(method) || method->force_inline();
 C2V_END
 
-C2V_ENTRY(jint, getCompiledCodeSize, (JNIEnv *env, jobject, jlong metaspace_method))
-  nmethod* code = (asMethod(metaspace_method))->code();
-  return code == NULL ? 0 : code->insts_size();
-C2V_END
-
 C2V_VMENTRY(jlong, lookupType, (JNIEnv *env, jobject, jstring jname, jclass accessing_class, jboolean resolve))
   ResourceMark rm;
   Handle name = JNIHandles::resolve(jname);
@@ -814,7 +809,6 @@
   {CC"doNotInlineOrCompile",                         CC"("METASPACE_METHOD")V",                                        FN_PTR(doNotInlineOrCompile)},
   {CC"canInlineMethod",                              CC"("METASPACE_METHOD")Z",                                        FN_PTR(canInlineMethod)},
   {CC"shouldInlineMethod",                           CC"("METASPACE_METHOD")Z",                                        FN_PTR(shouldInlineMethod)},
-  {CC"getCompiledCodeSize",                          CC"("METASPACE_METHOD")I",                                        FN_PTR(getCompiledCodeSize)},
   {CC"lookupType",                                   CC"("STRING CLASS"Z)"METASPACE_KLASS,                             FN_PTR(lookupType)},
   {CC"resolveConstantInPool",                        CC"("METASPACE_CONSTANT_POOL"I)"OBJECT,                           FN_PTR(resolveConstantInPool)},
   {CC"resolvePossiblyCachedConstantInPool",          CC"("METASPACE_CONSTANT_POOL"I)"OBJECT,                           FN_PTR(resolvePossiblyCachedConstantInPool)},
--- a/src/share/vm/graal/graalJavaAccess.hpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu Mar 20 13:50:21 2014 +0100
@@ -79,16 +79,7 @@
     oop_field(HotSpotCompiledCode, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;")                                                               \
     oop_field(HotSpotCompiledCode, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;")                                       \
     oop_field(HotSpotCompiledCode, comments, "[Lcom/oracle/graal/hotspot/HotSpotCompiledCode$Comment;")                                                        \
-    oop_field(HotSpotCompiledCode, dataSection, "Lcom/oracle/graal/hotspot/HotSpotCompiledCode$DataSection;")                                                  \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompiledCode_HotSpotData)                                                                                                                 \
-    int_field(HotSpotCompiledCode_HotSpotData, offset)                                                                                                         \
-    oop_field(HotSpotCompiledCode_HotSpotData, constant, "Lcom/oracle/graal/api/meta/Constant;")                                                               \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompiledCode_DataSection)                                                                                                                 \
-    int_field(HotSpotCompiledCode_DataSection, sectionAlignment)                                                                                               \
-    oop_field(HotSpotCompiledCode_DataSection, data, "[B")                                                                                                     \
-    oop_field(HotSpotCompiledCode_DataSection, patches, "[Lcom/oracle/graal/hotspot/HotSpotCompiledCode$HotSpotData;")                                         \
+    oop_field(HotSpotCompiledCode, dataSection, "Lcom/oracle/graal/hotspot/data/DataSection;")                                                                 \
   end_class                                                                                                                                                    \
   start_class(HotSpotCompiledCode_Comment)                                                                                                                     \
     oop_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;")                                                                                         \
@@ -97,7 +88,7 @@
   start_class(HotSpotCompiledNmethod)                                                                                                                          \
     oop_field(HotSpotCompiledNmethod, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;")                                                     \
     int_field(HotSpotCompiledNmethod, entryBCI)                                                                                                                \
-    int_field(HotSpotCompiledNmethod, id)                                                                                                                \
+    int_field(HotSpotCompiledNmethod, id)                                                                                                                      \
   end_class                                                                                                                                                    \
   start_class(HotSpotCompiledRuntimeStub)                                                                                                                      \
     oop_field(HotSpotCompiledRuntimeStub, stubName, "Ljava/lang/String;")                                                                                      \
@@ -105,6 +96,23 @@
   start_class(HotSpotForeignCallLinkage)                                                                                                                       \
     long_field(HotSpotForeignCallLinkage, address)                                                                                                             \
   end_class                                                                                                                                                    \
+  start_class(DataSection)                                                                                                                                     \
+    int_field(DataSection, sectionAlignment)                                                                                                                   \
+    oop_field(DataSection, data, "[B")                                                                                                                         \
+    oop_field(DataSection, patches, "[Lcom/oracle/graal/api/code/CompilationResult$DataPatch;")                                                                \
+  end_class                                                                                                                                                    \
+  start_class(DataSectionReference)                                                                                                                            \
+    int_field(DataSectionReference, offset)                                                                                                                    \
+  end_class                                                                                                                                                    \
+  start_class(MetaspaceData)                                                                                                                                   \
+    long_field(MetaspaceData, value)                                                                                                                           \
+    oop_field(MetaspaceData, annotation, "Ljava/lang/Object;")                                                                                                 \
+    boolean_field(MetaspaceData, compressed)                                                                                                                   \
+  end_class                                                                                                                                                    \
+  start_class(OopData)                                                                                                                                         \
+    oop_field(OopData, object, "Ljava/lang/Object;")                                                                                                           \
+    boolean_field(OopData, compressed)                                                                                                                         \
+  end_class                                                                                                                                                    \
   start_class(ExternalCompilationResult)                                                                                                                       \
     long_field(ExternalCompilationResult, entryPoint)                                                                                                          \
   end_class                                                                                                                                                    \
@@ -145,8 +153,7 @@
     oop_field(CompilationResult_Call, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;")                                                                      \
   end_class                                                                                                                                                    \
   start_class(CompilationResult_DataPatch)                                                                                                                     \
-    oop_field(CompilationResult_DataPatch, externalData, "Lcom/oracle/graal/api/code/CompilationResult$Data;")                                                 \
-    oop_field(CompilationResult_DataPatch, inlineData, "Lcom/oracle/graal/api/meta/Constant;")                                                                 \
+    oop_field(CompilationResult_DataPatch, data, "Lcom/oracle/graal/api/code/CompilationResult$Data;")                                                         \
   end_class                                                                                                                                                    \
   start_class(InfopointReason)                                                                                                                                 \
     static_oop_field(InfopointReason, UNKNOWN, "Lcom/oracle/graal/api/code/InfopointReason;")                                                                  \
@@ -172,9 +179,9 @@
     oop_field(DebugInfo, referenceMap, "Lcom/oracle/graal/api/code/ReferenceMap;")                                                                             \
     oop_field(DebugInfo, calleeSaveInfo, "Lcom/oracle/graal/api/code/RegisterSaveLayout;")                                                                     \
   end_class                                                                                                                                                    \
-  start_class(ReferenceMap)                                                                                                                                    \
-    oop_field(ReferenceMap, registerRefMap, "Ljava/util/BitSet;")                                                                                              \
-    oop_field(ReferenceMap, frameRefMap, "Ljava/util/BitSet;")                                                                                                 \
+  start_class(HotSpotReferenceMap)                                                                                                                             \
+    oop_field(HotSpotReferenceMap, registerRefMap, "Ljava/util/BitSet;")                                                                                       \
+    oop_field(HotSpotReferenceMap, frameRefMap, "Ljava/util/BitSet;")                                                                                          \
   end_class                                                                                                                                                    \
   start_class(RegisterSaveLayout)                                                                                                                              \
     oop_field(RegisterSaveLayout, registers, "[Lcom/oracle/graal/api/code/Register;")                                                                          \
--- a/src/share/vm/graal/graalRuntime.cpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/graal/graalRuntime.cpp	Thu Mar 20 13:50:21 2014 +0100
@@ -539,7 +539,12 @@
   Handle receiverHandle(thread, receiver);
   MutexLockerEx ml(thread->threadObj() == (void*)receiver ? NULL : Threads_lock);
   JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle());
-  return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0);
+  if (receiverThread == NULL) {
+    // The other thread may exit during this process, which is ok so return false.
+    return JNI_FALSE;
+  } else {
+    return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0);
+  }
 JRT_END
 
 // JVM_InitializeGraalRuntime
--- a/src/share/vm/graal/vmStructs_graal.hpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/graal/vmStructs_graal.hpp	Thu Mar 20 13:50:21 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,12 +26,14 @@
 #define SHARE_VM_GRAAL_VMSTRUCTS_GRAAL_HPP
 
 #include "compiler/abstractCompiler.hpp"
+#include "graal/graalCodeInstaller.hpp"
 #include "graal/graalCompilerToVM.hpp"
 #include "graal/graalEnv.hpp"
 
 #define VM_STRUCTS_GRAAL(nonstatic_field, static_field)                       \
   nonstatic_field(ThreadShadow, _pending_deoptimization, int)                 \
   nonstatic_field(ThreadShadow, _pending_failed_speculation, oop)             \
+  nonstatic_field(MethodData,   _graal_node_count, int)                       \
 
 #define VM_TYPES_GRAAL(declare_type, declare_toplevel_type)                   \
 
@@ -47,5 +49,21 @@
                                                                                                   \
   declare_constant(CompilerToVM::KLASS_TAG)                                                       \
   declare_constant(CompilerToVM::SYMBOL_TAG)                                                      \
+                                                                                                  \
+  declare_constant(CodeInstaller::VERIFIED_ENTRY)                                                 \
+  declare_constant(CodeInstaller::UNVERIFIED_ENTRY)                                               \
+  declare_constant(CodeInstaller::OSR_ENTRY)                                                      \
+  declare_constant(CodeInstaller::EXCEPTION_HANDLER_ENTRY)                                        \
+  declare_constant(CodeInstaller::DEOPT_HANDLER_ENTRY)                                            \
+  declare_constant(CodeInstaller::INVOKEINTERFACE)                                                \
+  declare_constant(CodeInstaller::INVOKEVIRTUAL)                                                  \
+  declare_constant(CodeInstaller::INVOKESTATIC)                                                   \
+  declare_constant(CodeInstaller::INVOKESPECIAL)                                                  \
+  declare_constant(CodeInstaller::INLINE_INVOKE)                                                  \
+  declare_constant(CodeInstaller::POLL_NEAR)                                                      \
+  declare_constant(CodeInstaller::POLL_RETURN_NEAR)                                               \
+  declare_constant(CodeInstaller::POLL_FAR)                                                       \
+  declare_constant(CodeInstaller::POLL_RETURN_FAR)                                                \
+  declare_constant(CodeInstaller::INVOKE_INVALID)                                                 \
 
 #endif // SHARE_VM_GRAAL_VMSTRUCTS_GRAAL_HPP
--- a/src/share/vm/oops/methodData.cpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/oops/methodData.cpp	Thu Mar 20 13:50:21 2014 +0100
@@ -1216,6 +1216,9 @@
   _highest_comp_level = 0;
   _highest_osr_comp_level = 0;
   _would_profile = true;
+#ifdef GRAAL
+  _graal_node_count = 0;
+#endif
 
   // Initialize flags and trap history.
   _nof_decompiles = 0;
--- a/src/share/vm/oops/methodData.hpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/oops/methodData.hpp	Thu Mar 20 13:50:21 2014 +0100
@@ -2203,6 +2203,11 @@
   // Does this method contain anything worth profiling?
   bool              _would_profile;
 
+#ifdef GRAAL
+  // Support for HotSpotMethodData.setCompiledGraphSize(int)
+  int               _graal_node_count;
+#endif
+
   // Size of _data array in bytes.  (Excludes header and extra_data fields.)
   int _data_size;
 
--- a/src/share/vm/utilities/globalDefinitions.hpp	Wed Mar 19 19:02:29 2014 +0100
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Thu Mar 20 13:50:21 2014 +0100
@@ -834,7 +834,7 @@
   CompLevel_full_profile      = 3,         // C1, invocation & backedge counters + mdo
   CompLevel_full_optimization = 4,         // C2, Shark or Graal
 
-#if defined(COMPILER2) || defined(SHARK) || defined(GRAAL)
+#if defined(COMPILER2) || defined(SHARK) || defined(COMPILERGRAAL)
   CompLevel_highest_tier      = CompLevel_full_optimization,  // pure C2 and tiered or Graal and tiered
 #elif defined(COMPILER1)
   CompLevel_highest_tier      = CompLevel_simple,             // pure C1 or Graal
@@ -844,7 +844,7 @@
 
 #if defined(TIERED)
   CompLevel_initial_compile   = CompLevel_full_profile        // tiered
-#elif defined(COMPILER1) || defined(GRAAL)
+#elif defined(COMPILER1) || defined(COMPILERGRAAL)
   CompLevel_initial_compile   = CompLevel_simple              // pure C1 or Graal
 #elif defined(COMPILER2) || defined(SHARK)
   CompLevel_initial_compile   = CompLevel_full_optimization   // pure C2