changeset 22263:7abe84b97eaa

Merge
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Mon, 20 Jul 2015 11:21:28 -0700
parents 71a696ca2862 (diff) 5c350399111e (current diff)
children 97ee41c80b1d
files jvmci/jdk.internal.jvmci.options.processor/src/jdk/internal/jvmci/options/processor/JVMCIJars.java
diffstat 31 files changed, 437 insertions(+), 142 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java	Mon Jul 20 11:21:28 2015 -0700
@@ -265,7 +265,7 @@
         int result = 1;
         result = prime * result + super.hashCode();
         result = prime * result + (exactType ? 1231 : 1237);
-        result = prime * result + ((type == null) ? 0 : type.hashCode());
+        result = prime * result + ((type == null || type.isJavaLangObject()) ? 0 : type.hashCode());
         return result;
     }
 
@@ -278,7 +278,19 @@
             return false;
         }
         AbstractObjectStamp other = (AbstractObjectStamp) obj;
-        if (exactType != other.exactType || !Objects.equals(type, other.type)) {
+        if (exactType != other.exactType) {
+            return false;
+        }
+        // null == java.lang.Object
+        if (type == null) {
+            if (other.type != null && !other.type.isJavaLangObject()) {
+                return false;
+            }
+        } else if (other.type == null) {
+            if (type != null && !type.isJavaLangObject()) {
+                return false;
+            }
+        } else if (!type.equals(other.type)) {
             return false;
         }
         return super.equals(other);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Mon Jul 20 11:21:28 2015 -0700
@@ -38,6 +38,7 @@
 import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.amd64.*;
@@ -76,7 +77,7 @@
             try (InitTimer rt = timer("create Lowerer provider")) {
                 lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target);
             }
-            HotSpotStampProvider stampProvider = new HotSpotStampProvider();
+            HotSpotStampProvider stampProvider = new HotSpotStampProvider(target.wordKind);
             Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, stampProvider);
 
             try (InitTimer rt = timer("create SnippetReflection provider")) {
@@ -86,7 +87,7 @@
                 replacements = createReplacements(runtime, p, snippetReflection);
             }
             try (InitTimer rt = timer("create WordTypes")) {
-                wordTypes = new HotSpotWordTypes(metaAccess, target.wordKind);
+                wordTypes = new HotSpotWordTypes(metaAccess, target.wordKind, stampProvider.createHubStamp(false), MethodPointerStamp.method());
             }
             try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
                 plugins = createGraphBuilderPlugins(runtime, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider);
@@ -167,15 +168,15 @@
         } else {
             /*
              * System V Application Binary Interface, AMD64 Architecture Processor Supplement
-             * 
+             *
              * Draft Version 0.96
-             * 
+             *
              * http://www.uclibc.org/docs/psABI-x86_64.pdf
-             * 
+             *
              * 3.2.1
-             * 
+             *
              * ...
-             * 
+             *
              * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12
              * through %r15 "belong" to the calling function and the called function is required to
              * preserve their values. In other words, a called function must preserve these
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Mon Jul 20 11:21:28 2015 -0700
@@ -35,6 +35,7 @@
 import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -56,11 +57,11 @@
         Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig());
         HotSpotForeignCallsProvider foreignCalls = new SPARCHotSpotForeignCallsProvider(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters);
         LoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target);
-        HotSpotStampProvider stampProvider = new HotSpotStampProvider();
+        HotSpotStampProvider stampProvider = new HotSpotStampProvider(codeCache.getTarget().wordKind);
         Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, stampProvider);
         HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime);
         HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), target);
-        HotSpotWordTypes wordTypes = new HotSpotWordTypes(metaAccess, target.wordKind);
+        HotSpotWordTypes wordTypes = new HotSpotWordTypes(metaAccess, target.wordKind, stampProvider.createHubStamp(false), MethodPointerStamp.method());
         Plugins plugins = createGraphBuilderPlugins(runtime, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes);
         replacements.setGraphBuilderPlugins(plugins);
         HotSpotSuitesProvider suites = createSuites(runtime, plugins, codeCache);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon Jul 20 11:21:28 2015 -0700
@@ -274,7 +274,7 @@
                 ResolvedJavaType receiverType = invoke.getReceiverType();
                 if (hsMethod.isInVirtualMethodTable(receiverType)) {
                     Kind wordKind = runtime.getTarget().wordKind;
-                    ValueNode hub = createReadHub(graph, receiver, receiverNullCheck);
+                    ValueNode hub = createReadHub(graph, receiver, receiverNullCheck, tool);
 
                     ReadNode metaspaceMethod = createReadVirtualMethod(graph, hub, hsMethod, receiverType);
                     // We use LocationNode.ANY_LOCATION for the reads that access the
@@ -332,13 +332,13 @@
     }
 
     @Override
-    protected ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor) {
+    protected ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor, LoweringTool tool) {
         /*
          * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass
          * is an object class, which might not be the case in other parts of the compiled method.
          */
         AddressNode address = createOffsetAddress(graph, arrayHub, runtime.getConfig().arrayClassElementOffset);
-        return graph.unique(new FloatingReadNode(address, OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION, null, KlassPointerStamp.klassNonNull(), AbstractBeginNode.prevBegin(anchor)));
+        return graph.unique(new FloatingReadNode(address, OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION, null, tool.getStampProvider().createHubStamp(true), AbstractBeginNode.prevBegin(anchor)));
     }
 
     @Override
@@ -485,11 +485,14 @@
     }
 
     @Override
-    protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard) {
+    protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard, LoweringTool tool) {
+        if (tool.getLoweringStage() != LoweringTool.StandardLoweringStage.LOW_TIER) {
+            return graph.unique(new LoadHubNode(tool.getStampProvider(), object, guard != null ? guard.asNode() : null));
+        }
         HotSpotVMConfig config = runtime.getConfig();
         assert !object.isConstant() || object.isNullConstant();
 
-        KlassPointerStamp hubStamp = KlassPointerStamp.klassNonNull();
+        KlassPointerStamp hubStamp = (KlassPointerStamp) tool.getStampProvider().createHubStamp(true);
         if (config.useCompressedClassPointers) {
             hubStamp = hubStamp.compressed(config.getKlassEncoding());
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java	Mon Jul 20 11:21:28 2015 -0700
@@ -47,7 +47,7 @@
     public HotSpotProviders(MetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls,
                     LoweringProvider lowerer, Replacements replacements, SuitesProvider suites, HotSpotRegistersProvider registers, SnippetReflectionProvider snippetReflection,
                     HotSpotWordTypes wordTypes, Plugins graphBuilderPlugins) {
-        super(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, new HotSpotStampProvider());
+        super(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, new HotSpotStampProvider(codeCache.getTarget().wordKind));
         this.suites = suites;
         this.registers = registers;
         this.snippetReflection = snippetReflection;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotStampProvider.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotStampProvider.java	Mon Jul 20 11:21:28 2015 -0700
@@ -22,17 +22,43 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import jdk.internal.jvmci.meta.*;
+
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.nodes.spi.*;
 
 public class HotSpotStampProvider implements StampProvider {
 
+    private final KlassPointerStamp klassStamp;
+
+    private final KlassPointerStamp klassNonNullStamp;
+
+    @SuppressWarnings("unused") private final Kind wordKind;
+
+    public HotSpotStampProvider(Kind wordKind) {
+        this.wordKind = wordKind;
+        klassStamp = new KlassPointerStamp(false, false, wordKind);
+        klassNonNullStamp = new KlassPointerStamp(true, false, wordKind);
+    }
+
+    public KlassPointerStamp klass() {
+        return klassStamp;
+    }
+
+    public KlassPointerStamp klassNonNull() {
+        return klassNonNullStamp;
+    }
+
     public Stamp createHubStamp(ObjectStamp object) {
-        return KlassPointerStamp.klassNonNull();
+        return klassNonNull();
     }
 
     public Stamp createMethodStamp() {
         return MethodPointerStamp.methodNonNull();
     }
+
+    public Stamp createHubStamp(boolean nonNull) {
+        return nonNull ? klassNonNullStamp : klassStamp;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java	Mon Jul 20 11:21:28 2015 -0700
@@ -43,17 +43,21 @@
 import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.word.*;
 
 /**
  * Extends {@link WordOperationPlugin} to handle {@linkplain HotSpotOperation HotSpot word
  * operations}.
  */
 class HotSpotWordOperationPlugin extends WordOperationPlugin {
-    public HotSpotWordOperationPlugin(SnippetReflectionProvider snippetReflection, WordTypes wordTypes) {
+
+    public HotSpotWordOperationPlugin(SnippetReflectionProvider snippetReflection, HotSpotWordTypes wordTypes) {
         super(snippetReflection, wordTypes);
     }
 
+    HotSpotWordTypes wordTypes() {
+        return (HotSpotWordTypes) wordTypes;
+    }
+
     @Override
     protected LoadIndexedNode createLoadIndexedNode(ValueNode array, ValueNode index) {
         ResolvedJavaType arrayType = StampTool.typeOrNull(array);
@@ -115,17 +119,17 @@
 
             case TO_KLASS_POINTER:
                 assert args.length == 1;
-                b.addPush(returnKind, new PointerCastNode(KlassPointerStamp.klass(), args[0]));
+                b.addPush(returnKind, new PointerCastNode(wordTypes().getKlassPointerStamp(), args[0]));
                 break;
 
             case TO_METHOD_POINTER:
                 assert args.length == 1;
-                b.addPush(returnKind, new PointerCastNode(MethodPointerStamp.method(), args[0]));
+                b.addPush(returnKind, new PointerCastNode(wordTypes().getMethodPointerStamp(), args[0]));
                 break;
 
             case READ_KLASS_POINTER:
                 assert args.length == 2 || args.length == 3;
-                Stamp readStamp = KlassPointerStamp.klass();
+                Stamp readStamp = wordTypes().getKlassPointerStamp();
                 AddressNode address = makeAddress(b, args[0], args[1]);
                 LocationIdentity location;
                 if (args.length == 2) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Mon Jul 20 11:21:28 2015 -0700
@@ -69,6 +69,10 @@
         return input.graph().unique(new CompressionNode(CompressionOp.Compress, input, encoding));
     }
 
+    public static CompressionNode compressNoUnique(ValueNode input, CompressEncoding encoding) {
+        return new CompressionNode(CompressionOp.Compress, input, encoding);
+    }
+
     public static CompressionNode uncompress(ValueNode input, CompressEncoding encoding) {
         return input.graph().unique(new CompressionNode(CompressionOp.Uncompress, input, encoding));
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/KlassPointerStamp.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/KlassPointerStamp.java	Mon Jul 20 11:21:28 2015 -0700
@@ -33,34 +33,23 @@
 
 public final class KlassPointerStamp extends MetaspacePointerStamp {
 
-    private static final KlassPointerStamp KLASS = new KlassPointerStamp(false, false);
-
-    private static final KlassPointerStamp KLASS_NON_NULL = new KlassPointerStamp(true, false);
-
-    private static final KlassPointerStamp KLASS_ALWAYS_NULL = new KlassPointerStamp(false, true);
-
     private final CompressEncoding encoding;
 
-    public static KlassPointerStamp klass() {
-        return KLASS;
+    private final Kind kind;
+
+    public KlassPointerStamp(boolean nonNull, boolean alwaysNull, Kind kind) {
+        this(nonNull, alwaysNull, null, kind);
     }
 
-    public static KlassPointerStamp klassNonNull() {
-        return KLASS_NON_NULL;
-    }
-
-    private KlassPointerStamp(boolean nonNull, boolean alwaysNull) {
-        this(nonNull, alwaysNull, null);
-    }
-
-    private KlassPointerStamp(boolean nonNull, boolean alwaysNull, CompressEncoding encoding) {
+    private KlassPointerStamp(boolean nonNull, boolean alwaysNull, CompressEncoding encoding, Kind kind) {
         super(nonNull, alwaysNull);
         this.encoding = encoding;
+        this.kind = kind;
     }
 
     @Override
     protected AbstractPointerStamp copyWith(boolean newNonNull, boolean newAlwaysNull) {
-        return new KlassPointerStamp(newNonNull, newAlwaysNull, encoding);
+        return new KlassPointerStamp(newNonNull, newAlwaysNull, encoding, kind);
     }
 
     @Override
@@ -79,23 +68,20 @@
     public Stamp constant(Constant c, MetaAccessProvider meta) {
         if (isCompressed()) {
             if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) {
-                return new KlassPointerStamp(false, true, encoding);
+                return new KlassPointerStamp(false, true, encoding, kind);
             }
         } else {
             if (JavaConstant.NULL_POINTER.equals(c)) {
-                return KLASS_ALWAYS_NULL;
+                return new KlassPointerStamp(false, true, encoding, kind);
             }
         }
 
         assert c instanceof HotSpotMetaspaceConstant;
+        assert ((HotSpotMetaspaceConstant) c).isCompressed() == isCompressed();
         if (nonNull()) {
             return this;
         }
-        if (isCompressed()) {
-            return new KlassPointerStamp(true, false, encoding);
-        } else {
-            return KLASS_NON_NULL;
-        }
+        return new KlassPointerStamp(true, false, encoding, kind);
     }
 
     @Override
@@ -126,12 +112,12 @@
 
     public KlassPointerStamp compressed(CompressEncoding newEncoding) {
         assert !isCompressed();
-        return new KlassPointerStamp(nonNull(), alwaysNull(), newEncoding);
+        return new KlassPointerStamp(nonNull(), alwaysNull(), newEncoding, Kind.Int);
     }
 
     public KlassPointerStamp uncompressed() {
         assert isCompressed();
-        return new KlassPointerStamp(nonNull(), alwaysNull());
+        return new KlassPointerStamp(nonNull(), alwaysNull(), Kind.Long);
     }
 
     @Override
@@ -176,4 +162,9 @@
         }
         return ret.toString();
     }
+
+    @Override
+    public Kind getStackKind() {
+        return isCompressed() ? Kind.Int : Kind.Long;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Mon Jul 20 11:21:28 2015 -0700
@@ -70,7 +70,7 @@
                 Stamp stamp = StampFactory.exactNonNull(metaAccess.lookupJavaType(Class.class));
 
                 if (type instanceof HotSpotResolvedObjectType) {
-                    ConstantNode klass = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) type).klass(), metaAccess, graph);
+                    ConstantNode klass = ConstantNode.forConstant(context.getStampProvider().createHubStamp(true), ((HotSpotResolvedObjectType) type).klass(), metaAccess, graph);
                     AddressNode address = graph.unique(new OffsetAddressNode(klass, ConstantNode.forLong(classMirrorOffset, graph)));
                     ValueNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, stamp));
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java	Mon Jul 20 11:21:28 2015 -0700
@@ -28,7 +28,6 @@
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
@@ -48,14 +47,16 @@
 public final class ClassGetHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode {
     public static final NodeClass<ClassGetHubNode> TYPE = NodeClass.create(ClassGetHubNode.class);
     @Input protected ValueNode clazz;
+    StampProvider stampProvider;
 
-    public ClassGetHubNode(ValueNode clazz) {
-        this(clazz, null);
+    public ClassGetHubNode(@InjectedNodeParameter StampProvider stampProvider, ValueNode clazz) {
+        this(stampProvider, clazz, null);
     }
 
-    public ClassGetHubNode(ValueNode clazz, ValueNode guard) {
-        super(TYPE, KlassPointerStamp.klass(), (GuardingNode) guard);
+    public ClassGetHubNode(@InjectedNodeParameter StampProvider stampProvider, ValueNode clazz, ValueNode guard) {
+        super(TYPE, stampProvider.createHubStamp(false), (GuardingNode) guard);
         this.clazz = clazz;
+        this.stampProvider = stampProvider;
     }
 
     @Override
@@ -78,7 +79,7 @@
             }
             if (clazz instanceof GetClassNode) {
                 GetClassNode getClass = (GetClassNode) clazz;
-                return new LoadHubNode(KlassPointerStamp.klassNonNull(), getClass.getObject(), null);
+                return new LoadHubNode(stampProvider, getClass.getObject(), null);
             }
             if (clazz instanceof HubGetClassNode) {
                 // replace _klass._java_mirror._klass -> _klass
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Jul 20 11:21:28 2015 -0700
@@ -22,22 +22,29 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import jdk.internal.jvmci.code.*;
-import jdk.internal.jvmci.common.*;
-import jdk.internal.jvmci.hotspot.*;
-import jdk.internal.jvmci.meta.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
 import static jdk.internal.jvmci.common.UnsafeAccess.*;
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.common.*;
+import jdk.internal.jvmci.hotspot.*;
+import jdk.internal.jvmci.meta.Assumptions.AssumptionResult;
+import jdk.internal.jvmci.meta.*;
 
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.word.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
@@ -49,6 +56,60 @@
  */
 public class HotSpotReplacementsUtil {
 
+    abstract static class HotSpotOptimizingLocationIdentity extends NamedLocationIdentity implements CanonicalizableLocation {
+
+        HotSpotOptimizingLocationIdentity(String name) {
+            super(name, true);
+        }
+
+        @Override
+        public abstract ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool);
+
+        protected ValueNode findReadHub(ValueNode object) {
+            ValueNode base = object;
+            if (base instanceof CompressionNode) {
+                base = ((CompressionNode) base).getValue();
+            }
+            if (base instanceof Access) {
+                Access access = (Access) base;
+                if (access.getLocationIdentity().equals(HUB_LOCATION)) {
+                    AddressNode address = access.getAddress();
+                    if (address instanceof OffsetAddressNode) {
+                        OffsetAddressNode offset = (OffsetAddressNode) address;
+                        return offset.getBase();
+                    }
+                }
+            } else if (base instanceof LoadHubNode) {
+                LoadHubNode loadhub = (LoadHubNode) base;
+                return loadhub.getValue();
+            }
+            return null;
+        }
+
+        /**
+         * Fold reads that convert from Class -> Hub -> Class or vice versa.
+         *
+         * @param read
+         * @param object
+         * @param otherLocation
+         * @return an earlier read or the original {@code read}
+         */
+        protected static ValueNode foldIndirection(ValueNode read, ValueNode object, LocationIdentity otherLocation) {
+            if (object instanceof Access) {
+                Access access = (Access) object;
+                if (access.getLocationIdentity().equals(otherLocation)) {
+                    AddressNode address = access.getAddress();
+                    if (address instanceof OffsetAddressNode) {
+                        OffsetAddressNode offset = (OffsetAddressNode) address;
+                        assert offset.getBase().stamp().isCompatible(read.stamp());
+                        return offset.getBase();
+                    }
+                }
+            }
+            return read;
+        }
+    }
+
     @Fold
     public static HotSpotVMConfig config() {
         return runtime().getConfig();
@@ -296,7 +357,23 @@
         return config().jvmAccWrittenFlags;
     }
 
-    public static final LocationIdentity KLASS_LAYOUT_HELPER_LOCATION = NamedLocationIdentity.immutable("Klass::_layout_helper");
+    public static final LocationIdentity KLASS_LAYOUT_HELPER_LOCATION = new HotSpotOptimizingLocationIdentity("Klass::_layout_helper") {
+        @Override
+        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
+            ValueNode javaObject = findReadHub(object);
+            if (javaObject != null) {
+                if (javaObject.stamp() instanceof ObjectStamp) {
+                    ObjectStamp stamp = (ObjectStamp) javaObject.stamp();
+                    HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) stamp.javaType(tool.getMetaAccess());
+                    if (type.isArray() && !type.getComponentType().isPrimitive()) {
+                        int layout = ((HotSpotResolvedObjectTypeImpl) type).layoutHelper();
+                        return ConstantNode.forInt(layout);
+                    }
+                }
+            }
+            return read;
+        }
+    };
 
     @Fold
     public static int klassLayoutHelperOffset() {
@@ -356,7 +433,20 @@
 
     public static final LocationIdentity HUB_WRITE_LOCATION = NamedLocationIdentity.mutable("Hub:write");
 
-    public static final LocationIdentity HUB_LOCATION = NamedLocationIdentity.immutable("Hub");
+    public static final LocationIdentity HUB_LOCATION = new HotSpotOptimizingLocationIdentity("Hub") {
+        @Override
+        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
+            ResolvedJavaType constantType = LoadHubNode.findSynonymType(read.graph(), tool.getMetaAccess(), object);
+            if (constantType != null) {
+                if (config().useCompressedClassPointers) {
+                    return ConstantNode.forConstant(read.stamp(), ((HotSpotMetaspaceConstant) constantType.getObjectHub()).compress(config().getKlassEncoding()), tool.getMetaAccess());
+                } else {
+                    return ConstantNode.forConstant(read.stamp(), constantType.getObjectHub(), tool.getMetaAccess());
+                }
+            }
+            return read;
+        }
+    };
 
     @Fold
     private static int hubOffset() {
@@ -578,6 +668,11 @@
         return loadWordFromObjectIntrinsic(object, offset, getWordKind(), identity);
     }
 
+    public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) {
+        ReplacementsUtil.staticAssert(offset != hubOffset(), "Use loadHubIntrinsic instead of loadWordFromObject");
+        return loadKlassFromObjectIntrinsic(object, offset, getWordKind(), identity);
+    }
+
     /**
      * Reads the value of a given register.
      *
@@ -597,6 +692,9 @@
     @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
     private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity);
 
+    @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
+    private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity);
+
     @NodeIntrinsic(value = LoadHubNode.class)
     public static native KlassPointer loadHubIntrinsic(Object object, GuardingNode anchor);
 
@@ -647,14 +745,24 @@
         return config().klassModifierFlagsOffset;
     }
 
-    public static final LocationIdentity CLASS_KLASS_LOCATION = NamedLocationIdentity.immutable("Class._klass");
+    public static final LocationIdentity CLASS_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._klass") {
+        @Override
+        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
+            return foldIndirection(read, object, CLASS_MIRROR_LOCATION);
+        }
+    };
 
     @Fold
     public static int klassOffset() {
         return config().klassOffset;
     }
 
-    public static final LocationIdentity CLASS_ARRAY_KLASS_LOCATION = NamedLocationIdentity.mutable("Class._array_klass");
+    public static final LocationIdentity CLASS_ARRAY_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._array_klass") {
+        @Override
+        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
+            return foldIndirection(read, object, ARRAY_KLASS_COMPONENT_MIRROR);
+        }
+    };
 
     @Fold
     public static int arrayKlassOffset() {
@@ -846,7 +954,26 @@
         }
     }
 
-    public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = NamedLocationIdentity.immutable("ObjArrayKlass::_element_klass");
+    public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("ObjArrayKlass::_element_klass") {
+        @Override
+        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
+            ValueNode javaObject = findReadHub(object);
+            if (javaObject != null) {
+                ResolvedJavaType type = StampTool.typeOrNull(javaObject);
+                if (type != null && type.isArray()) {
+                    ResolvedJavaType element = type.getComponentType();
+                    if (element != null && !element.isPrimitive() && !element.getElementalType().isInterface()) {
+                        AssumptionResult<ResolvedJavaType> leafType = element.findLeafConcreteSubtype();
+                        if (leafType != null) {
+                            object.graph().getAssumptions().record(leafType);
+                            return ConstantNode.forConstant(read.stamp(), leafType.getResult().getObjectHub(), tool.getMetaAccess());
+                        }
+                    }
+                }
+            }
+            return read;
+        }
+    };
 
     @Fold
     public static int arrayClassElementOffset() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Jul 20 11:21:28 2015 -0700
@@ -37,7 +37,6 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.nodes.*;
@@ -229,38 +228,39 @@
 
         @Override
         protected Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) {
+            Stamp hubStamp = tool.getStampProvider().createHubStamp(true);
             if (replacer.instanceOf instanceof InstanceOfNode) {
                 InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf;
                 ValueNode object = instanceOf.getValue();
                 Assumptions assumptions = instanceOf.graph().getAssumptions();
                 TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), assumptions, TypeCheckMinProfileHitProbability.getValue(), TypeCheckMaxHints.getValue());
                 final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type();
-                ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), instanceOf.graph());
+                ConstantNode hub = ConstantNode.forConstant(hubStamp, type.klass(), providers.getMetaAccess(), instanceOf.graph());
 
                 Arguments args;
 
                 StructuredGraph graph = instanceOf.graph();
                 if (hintInfo.hintHitProbability >= 1.0 && hintInfo.exact == null) {
-                    Hints hints = createHints(hintInfo, providers.getMetaAccess(), false, graph);
+                    Hints hints = createHints(hintInfo, providers.getMetaAccess(), false, graph, tool);
                     args = new Arguments(instanceofWithProfile, graph.getGuardsStage(), tool.getLoweringStage());
                     args.add("object", object);
-                    args.addVarargs("hints", KlassPointer.class, KlassPointerStamp.klassNonNull(), hints.hubs);
+                    args.addVarargs("hints", KlassPointer.class, hubStamp, hints.hubs);
                     args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive);
                 } else if (hintInfo.exact != null) {
                     args = new Arguments(instanceofExact, graph.getGuardsStage(), tool.getLoweringStage());
                     args.add("object", object);
-                    args.add("exactHub", ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) hintInfo.exact).klass(), providers.getMetaAccess(), graph));
+                    args.add("exactHub", ConstantNode.forConstant(hubStamp, ((HotSpotResolvedObjectType) hintInfo.exact).klass(), providers.getMetaAccess(), graph));
                 } else if (type.isPrimaryType()) {
                     args = new Arguments(instanceofPrimary, graph.getGuardsStage(), tool.getLoweringStage());
                     args.add("hub", hub);
                     args.add("object", object);
                     args.addConst("superCheckOffset", type.superCheckOffset());
                 } else {
-                    Hints hints = createHints(hintInfo, providers.getMetaAccess(), false, graph);
+                    Hints hints = createHints(hintInfo, providers.getMetaAccess(), false, graph, tool);
                     args = new Arguments(instanceofSecondary, graph.getGuardsStage(), tool.getLoweringStage());
                     args.add("hub", hub);
                     args.add("object", object);
-                    args.addVarargs("hints", KlassPointer.class, KlassPointerStamp.klassNonNull(), hints.hubs);
+                    args.addVarargs("hints", KlassPointer.class, hubStamp, hints.hubs);
                     args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive);
                 }
                 args.add("trueValue", replacer.trueValue);
@@ -275,7 +275,7 @@
                 ValueNode object = typeCheck.getValue();
                 Arguments args = new Arguments(instanceofExact, typeCheck.graph().getGuardsStage(), tool.getLoweringStage());
                 args.add("object", object);
-                args.add("exactHub", ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) typeCheck.type()).klass(), providers.getMetaAccess(), typeCheck.graph()));
+                args.add("exactHub", ConstantNode.forConstant(hubStamp, ((HotSpotResolvedObjectType) typeCheck.type()).klass(), providers.getMetaAccess(), typeCheck.graph()));
                 args.add("trueValue", replacer.trueValue);
                 args.add("falseValue", replacer.falseValue);
                 return args;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Jul 20 11:21:28 2015 -0700
@@ -47,7 +47,6 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.debug.*;
@@ -197,7 +196,8 @@
     @Snippet
     public static Object allocateArray(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
                     @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) {
-        return allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false);
+        Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false);
+        return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic());
     }
 
     private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents,
@@ -219,7 +219,7 @@
             result = newArray(HotSpotBackend.NEW_ARRAY, hub, length);
         }
         profileAllocation("array", allocationSize, typeContext);
-        return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic());
+        return result;
     }
 
     @NodeIntrinsic(ForeignCallNode.class)
@@ -240,7 +240,12 @@
 
     @Snippet
     public static Object allocateArrayDynamic(Class<?> elementType, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
-                    @ConstantParameter Kind knownElementKind) {
+                    @ConstantParameter Kind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord) {
+        Object result = allocateArrayDynamicImpl(elementType, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord);
+        return result;
+    }
+
+    private static Object allocateArrayDynamicImpl(Class<?> elementType, int length, boolean fillContents, Register threadRegister, Kind knownElementKind, int knownLayoutHelper, Word prototypeMarkWord) {
         /*
          * We only need the dynamic check for void when we have no static information from
          * knownElementKind.
@@ -250,13 +255,11 @@
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
 
-        Word hub = loadWordFromObject(elementType, arrayKlassOffset(), CLASS_ARRAY_KLASS_LOCATION);
-        if (probability(BranchProbabilityNode.NOT_FREQUENT_PROBABILITY, hub.equal(Word.zero()) || !belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH))) {
-            return dynamicNewArrayStub(DYNAMIC_NEW_ARRAY, elementType, length);
+        KlassPointer klass = loadKlassFromObject(elementType, arrayKlassOffset(), CLASS_ARRAY_KLASS_LOCATION);
+        if (probability(BranchProbabilityNode.NOT_FREQUENT_PROBABILITY, klass.isNull() || length < 0)) {
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
-
-        KlassPointer klass = KlassPointer.fromWord(hub);
-        int layoutHelper = readLayoutHelper(klass);
+        int layoutHelper = knownElementKind != Kind.Illegal ? knownLayoutHelper : readLayoutHelper(klass);
         //@formatter:off
         // from src/share/vm/oops/klass.hpp:
         //
@@ -272,9 +275,9 @@
 
         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
-        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
 
-        return allocateArrayImpl(klass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true);
+        Object result = allocateArrayImpl(klass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true);
+        return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic());
     }
 
     /**
@@ -445,7 +448,7 @@
             StructuredGraph graph = newInstanceNode.graph();
             HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newInstanceNode.instanceClass();
             assert !type.isArray();
-            ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), graph);
+            ConstantNode hub = ConstantNode.forConstant(tool.getStampProvider().createHubStamp(true), type.klass(), providers.getMetaAccess(), graph);
             int size = instanceSize(type);
 
             Arguments args = new Arguments(allocateInstance, graph.getGuardsStage(), tool.getLoweringStage());
@@ -470,7 +473,7 @@
             ResolvedJavaType elementType = newArrayNode.elementType();
             HotSpotResolvedObjectType arrayType = (HotSpotResolvedObjectType) elementType.getArrayClass();
             Kind elementKind = elementType.getKind();
-            ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), arrayType.klass(), providers.getMetaAccess(), graph);
+            ConstantNode hub = ConstantNode.forConstant(tool.getStampProvider().createHubStamp(true), arrayType.klass(), providers.getMetaAccess(), graph);
             final int headerSize = runtime.getJVMCIRuntime().getArrayBaseOffset(elementKind);
             HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
             int log2ElementSize = CodeUtil.log2(lowerer.arrayScalingFactor(elementKind));
@@ -479,6 +482,7 @@
             args.add("hub", hub);
             ValueNode length = newArrayNode.length();
             args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length));
+            assert arrayType.prototypeMarkWord() == lookupArrayClass(tool, Kind.Object).prototypeMarkWord() : "all array types are assumed to have the same prototypeMarkWord";
             args.add("prototypeMarkWord", arrayType.prototypeMarkWord());
             args.addConst("headerSize", headerSize);
             args.addConst("log2ElementSize", log2ElementSize);
@@ -515,11 +519,20 @@
              * parameters cannot be null.
              */
             args.addConst("knownElementKind", newArrayNode.getKnownElementKind() == null ? Kind.Illegal : newArrayNode.getKnownElementKind());
-
+            if (newArrayNode.getKnownElementKind() != null) {
+                args.addConst("knownLayoutHelper", lookupArrayClass(tool, newArrayNode.getKnownElementKind()).layoutHelper());
+            } else {
+                args.addConst("knownLayoutHelper", 0);
+            }
+            args.add("prototypeMarkWord", lookupArrayClass(tool, Kind.Object).prototypeMarkWord());
             SnippetTemplate template = template(args);
             template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args);
         }
 
+        private static HotSpotResolvedObjectType lookupArrayClass(LoweringTool tool, Kind kind) {
+            return (HotSpotResolvedObjectType) tool.getMetaAccess().lookupJavaType(kind == Kind.Object ? Object.class : kind.toJavaClass()).getArrayClass();
+        }
+
         public void lower(NewMultiArrayNode newmultiarrayNode, LoweringTool tool) {
             StructuredGraph graph = newmultiarrayNode.graph();
             int rank = newmultiarrayNode.dimensionCount();
@@ -528,7 +541,7 @@
                 dims[i] = newmultiarrayNode.dimension(i);
             }
             HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type();
-            ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), graph);
+            ConstantNode hub = ConstantNode.forConstant(tool.getStampProvider().createHubStamp(true), type.klass(), providers.getMetaAccess(), graph);
 
             Arguments args = new Arguments(newmultiarray, graph.getGuardsStage(), tool.getLoweringStage());
             args.add("hub", hub);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Mon Jul 20 11:21:28 2015 -0700
@@ -32,9 +32,9 @@
 import jdk.internal.jvmci.hotspot.*;
 import jdk.internal.jvmci.meta.*;
 
-import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
 
@@ -122,13 +122,13 @@
         }
     }
 
-    static Hints createHints(TypeCheckHints hints, MetaAccessProvider metaAccess, boolean positiveOnly, StructuredGraph graph) {
+    static Hints createHints(TypeCheckHints hints, MetaAccessProvider metaAccess, boolean positiveOnly, StructuredGraph graph, LoweringTool tool) {
         ConstantNode[] hubs = new ConstantNode[hints.hints.length];
         boolean[] isPositive = new boolean[hints.hints.length];
         int index = 0;
         for (int i = 0; i < hubs.length; i++) {
             if (!positiveOnly || hints.hints[i].positive) {
-                hubs[index] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) hints.hints[i].type).klass(), metaAccess, graph);
+                hubs[index] = ConstantNode.forConstant(tool.getStampProvider().createHubStamp(true), ((HotSpotResolvedObjectType) hints.hints[i].type).klass(), metaAccess, graph);
                 isPositive[index] = hints.hints[i].positive;
                 index++;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java	Mon Jul 20 11:21:28 2015 -0700
@@ -38,7 +38,6 @@
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -525,7 +524,7 @@
             }
             if (snippetInfo == arraycopyPredictedObjectWorkSnippet) {
                 HotSpotResolvedObjectType arrayKlass = (HotSpotResolvedObjectType) tool.getMetaAccess().lookupJavaType(Object[].class);
-                ValueNode objectArrayKlass = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), arrayKlass.klass(), tool.getMetaAccess(), arraycopy.graph());
+                ValueNode objectArrayKlass = ConstantNode.forConstant(tool.getStampProvider().createHubStamp(true), arrayKlass.klass(), tool.getMetaAccess(), arraycopy.graph());
                 args.add("objectArrayKlass", objectArrayKlass);
                 args.addConst("counter", arraycopyCallCounters.get(Kind.Object));
                 args.addConst("copiedCounter", arraycopyCallCopiedCounters.get(Kind.Object));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Mon Jul 20 11:21:28 2015 -0700
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
-import jdk.internal.jvmci.code.*;
-import jdk.internal.jvmci.hotspot.*;
-import jdk.internal.jvmci.meta.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
 import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
 import static com.oracle.graal.hotspot.stubs.StubUtil.*;
 import static jdk.internal.jvmci.hotspot.HotSpotMetaAccessProvider.*;
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.hotspot.*;
+import jdk.internal.jvmci.meta.*;
 
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
@@ -37,7 +37,6 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.nodes.*;
@@ -64,7 +63,7 @@
         Object[] args = new Object[count];
         assert checkConstArg(2, "intArrayHub");
         assert checkConstArg(3, "threadRegister");
-        args[2] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null);
+        args[2] = ConstantNode.forConstant(providers.getStampProvider().createHubStamp(true), intArrayType.klass(), null);
         args[3] = providers.getRegisters().getThreadRegister();
         return args;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Jul 20 11:21:28 2015 -0700
@@ -36,7 +36,6 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.nodes.*;
@@ -64,7 +63,7 @@
         Object[] args = new Object[count];
         assert checkConstArg(1, "intArrayHub");
         assert checkConstArg(2, "threadRegister");
-        args[1] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null);
+        args[1] = ConstantNode.forConstant(providers.getStampProvider().createHubStamp(true), intArrayType.klass(), null);
         args[2] = providers.getRegisters().getThreadRegister();
         return args;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypes.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypes.java	Mon Jul 20 11:21:28 2015 -0700
@@ -25,7 +25,6 @@
 import jdk.internal.jvmci.meta.*;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -48,11 +47,17 @@
      */
     private final ResolvedJavaType methodPointerType;
 
-    public HotSpotWordTypes(MetaAccessProvider metaAccess, Kind wordKind) {
+    private final Stamp klassPointerStamp;
+
+    private final Stamp methodPointerStamp;
+
+    public HotSpotWordTypes(MetaAccessProvider metaAccess, Kind wordKind, Stamp klassPointerStamp, Stamp methodPointerStamp) {
         super(metaAccess, wordKind);
         this.metaspacePointerType = metaAccess.lookupJavaType(MetaspacePointer.class);
         this.klassPointerType = metaAccess.lookupJavaType(KlassPointer.class);
         this.methodPointerType = metaAccess.lookupJavaType(MethodPointer.class);
+        this.klassPointerStamp = klassPointerStamp;
+        this.methodPointerStamp = methodPointerStamp;
     }
 
     @Override
@@ -74,10 +79,18 @@
     @Override
     public Stamp getWordStamp(ResolvedJavaType type) {
         if (type.equals(klassPointerType)) {
-            return KlassPointerStamp.klass();
+            return klassPointerStamp;
         } else if (type.equals(methodPointerType)) {
-            return MethodPointerStamp.method();
+            return methodPointerStamp;
         }
         return super.getWordStamp(type);
     }
+
+    public Stamp getKlassPointerStamp() {
+        return klassPointerStamp;
+    }
+
+    public Stamp getMethodPointerStamp() {
+        return methodPointerStamp;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CanonicalizableLocation.java	Mon Jul 20 11:21:28 2015 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.memory.address.*;
+
+public interface CanonicalizableLocation {
+    ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool);
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Mon Jul 20 11:21:28 2015 -0700
@@ -106,6 +106,23 @@
         if (stamp().equals(object().stamp())) {
             return object();
         }
+        if (getGuard() != null) {
+            for (Node use : getGuard().asNode().usages()) {
+                if (use instanceof PiNode) {
+                    PiNode otherPi = (PiNode) use;
+                    if (object() == otherPi.object() && stamp().equals(otherPi.stamp())) {
+                        /*
+                         * Two PiNodes with the same guard and same result, so return the one with
+                         * the more precise piStamp.
+                         */
+                        Stamp newStamp = piStamp.join(otherPi.piStamp);
+                        if (newStamp.equals(otherPi.piStamp)) {
+                            return otherPi;
+                        }
+                    }
+                }
+            }
+        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Mon Jul 20 11:21:28 2015 -0700
@@ -25,13 +25,15 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 /**
  * Value {@link PhiNode}s merge data flow values at control flow merges.
  */
 @NodeInfo(nameTemplate = "Phi({i#values})")
-public class ValuePhiNode extends PhiNode {
+public class ValuePhiNode extends PhiNode implements ArrayLengthProvider {
 
     public static final NodeClass<ValuePhiNode> TYPE = NodeClass.create(ValuePhiNode.class);
     @Input protected NodeInputList<ValueNode> values;
@@ -65,4 +67,23 @@
         }
         return updateStamp(valuesStamp);
     }
+
+    public ValueNode length() {
+        if (merge() instanceof LoopBeginNode) {
+            return null;
+        }
+        ValueNode length = null;
+        for (ValueNode input : values()) {
+            ValueNode l = GraphUtil.arrayLength(input);
+            if (l == null) {
+                return null;
+            }
+            if (length == null) {
+                length = l;
+            } else if (length != l) {
+                return null;
+            }
+        }
+        return length;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Mon Jul 20 11:21:28 2015 -0700
@@ -67,7 +67,7 @@
         this(hubStamp(stampProvider, value), value, guard);
     }
 
-    public LoadHubNode(Stamp stamp, ValueNode value, ValueNode guard) {
+    private LoadHubNode(Stamp stamp, ValueNode value, ValueNode guard) {
         super(TYPE, stamp, (GuardingNode) guard);
         assert value != guard;
         this.value = value;
@@ -75,9 +75,6 @@
 
     @Override
     public void lower(LoweringTool tool) {
-        if (tool.getLoweringStage() != LoweringTool.StandardLoweringStage.LOW_TIER) {
-            return;
-        }
         tool.getLowerer().lower(this, tool);
     }
 
@@ -92,10 +89,18 @@
         return this;
     }
 
-    private static ValueNode findSynonym(ValueNode curValue, Stamp stamp, StructuredGraph graph, MetaAccessProvider metaAccess) {
+    public static ValueNode findSynonym(ValueNode curValue, Stamp stamp, StructuredGraph graph, MetaAccessProvider metaAccess) {
+        ResolvedJavaType exactType = findSynonymType(graph, metaAccess, curValue);
+        if (exactType != null) {
+            return ConstantNode.forConstant(stamp, exactType.getObjectHub(), metaAccess);
+        }
+        return null;
+    }
+
+    public static ResolvedJavaType findSynonymType(StructuredGraph graph, MetaAccessProvider metaAccess, ValueNode curValue) {
+        ResolvedJavaType exactType = null;
         if (metaAccess != null && curValue.stamp() instanceof ObjectStamp) {
             ObjectStamp objectStamp = (ObjectStamp) curValue.stamp();
-            ResolvedJavaType exactType = null;
             if (objectStamp.isExactType()) {
                 exactType = objectStamp.type();
             } else if (objectStamp.type() != null && graph != null && graph.getAssumptions() != null) {
@@ -105,12 +110,8 @@
                     graph.getAssumptions().record(leafConcreteSubtype);
                 }
             }
-
-            if (exactType != null) {
-                return ConstantNode.forConstant(stamp, exactType.getObjectHub(), metaAccess);
-            }
         }
-        return null;
+        return exactType;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Mon Jul 20 11:21:28 2015 -0700
@@ -47,12 +47,25 @@
      */
     protected final Kind knownElementKind;
 
-    public DynamicNewArrayNode(ValueNode elementType, ValueNode length, boolean fillContents, Kind knownElementKind) {
-        this(TYPE, elementType, length, fillContents, knownElementKind, null);
+    public DynamicNewArrayNode(ValueNode elementType, ValueNode length, boolean fillContents) {
+        this(TYPE, elementType, length, fillContents, null, null, null);
+    }
+
+    public DynamicNewArrayNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ValueNode elementType, ValueNode length, boolean fillContents, Kind knownElementKind) {
+        this(TYPE, elementType, length, fillContents, knownElementKind, null, metaAccess);
     }
 
-    protected DynamicNewArrayNode(NodeClass<? extends DynamicNewArrayNode> c, ValueNode elementType, ValueNode length, boolean fillContents, Kind knownElementKind, FrameState stateBefore) {
-        super(c, StampFactory.objectNonNull(), length, fillContents, stateBefore);
+    private static Stamp computeStamp(Kind knownElementKind, MetaAccessProvider metaAccess) {
+        if (knownElementKind != null && metaAccess != null) {
+            ResolvedJavaType arrayType = metaAccess.lookupJavaType(knownElementKind == Kind.Object ? Object.class : knownElementKind.toJavaClass()).getArrayClass();
+            return StampFactory.declaredNonNull(arrayType);
+        }
+        return StampFactory.objectNonNull();
+    }
+
+    protected DynamicNewArrayNode(NodeClass<? extends DynamicNewArrayNode> c, ValueNode elementType, ValueNode length, boolean fillContents, Kind knownElementKind, FrameState stateBefore,
+                    MetaAccessProvider metaAccess) {
+        super(c, computeStamp(knownElementKind, metaAccess), length, fillContents, stateBefore);
         this.elementType = elementType;
         this.knownElementKind = knownElementKind;
         assert knownElementKind != Kind.Void && knownElementKind != Kind.Illegal;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/ReadNode.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/ReadNode.java	Mon Jul 20 11:21:28 2015 -0700
@@ -133,6 +133,13 @@
                     return length;
                 }
             }
+            if (locationIdentity instanceof CanonicalizableLocation) {
+                CanonicalizableLocation canonicalize = (CanonicalizableLocation) locationIdentity;
+                ValueNode result = canonicalize.canonicalizeRead(read, address, object, tool);
+                assert result != null && result.stamp().isCompatible(read.stamp());
+                return result;
+            }
+
         }
         return read;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/StampProvider.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/StampProvider.java	Mon Jul 20 11:21:28 2015 -0700
@@ -36,6 +36,11 @@
     Stamp createHubStamp(ObjectStamp object);
 
     /**
+     * Create the stamp of a possibly null hub.
+     */
+    Stamp createHubStamp(boolean nonNull);
+
+    /**
      * Create the stamp of a pointer to a method.
      */
     Stamp createMethodStamp();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Mon Jul 20 11:21:28 2015 -0700
@@ -87,7 +87,7 @@
         } else if (n instanceof ArrayLengthNode) {
             lowerArrayLengthNode((ArrayLengthNode) n, tool);
         } else if (n instanceof LoadHubNode) {
-            lowerLoadHubNode((LoadHubNode) n);
+            lowerLoadHubNode((LoadHubNode) n, tool);
         } else if (n instanceof MonitorEnterNode) {
             lowerMonitorEnterNode((MonitorEnterNode) n, tool, graph);
         } else if (n instanceof CompareAndSwapNode) {
@@ -118,7 +118,7 @@
     }
 
     private void lowerTypeCheckNode(TypeCheckNode n, LoweringTool tool, StructuredGraph graph) {
-        ValueNode hub = createReadHub(graph, n.getValue(), null);
+        ValueNode hub = createReadHub(graph, n.getValue(), null, tool);
         ValueNode clazz = graph.unique(ConstantNode.forConstant(tool.getStampProvider().createHubStamp((ObjectStamp) n.getValue().stamp()), n.type().getObjectHub(), tool.getMetaAccess()));
         LogicNode objectEquals = graph.unique(PointerEqualsNode.create(hub, clazz));
         n.replaceAndDelete(objectEquals);
@@ -270,8 +270,8 @@
                  */
                 GuardingNode nullCheck = nullCheckReturn[0];
                 assert nullCheckReturn[0] != null || createNullCheck(array, storeIndexed, tool) == null;
-                ValueNode arrayClass = createReadHub(graph, array, nullCheck);
-                ValueNode componentHub = createReadArrayComponentHub(graph, arrayClass, storeIndexed);
+                ValueNode arrayClass = createReadHub(graph, array, nullCheck, tool);
+                ValueNode componentHub = createReadArrayComponentHub(graph, arrayClass, storeIndexed, tool);
                 checkCastNode = graph.add(new CheckCastDynamicNode(componentHub, value, true));
                 graph.addBeforeFixed(storeIndexed, checkCastNode);
                 value = checkCastNode;
@@ -301,12 +301,15 @@
         graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead);
     }
 
-    protected void lowerLoadHubNode(LoadHubNode loadHub) {
+    protected void lowerLoadHubNode(LoadHubNode loadHub, LoweringTool tool) {
         StructuredGraph graph = loadHub.graph();
+        if (tool.getLoweringStage() != LoweringTool.StandardLoweringStage.LOW_TIER) {
+            return;
+        }
         if (graph.getGuardsStage().allowsFloatingGuards()) {
             return;
         }
-        ValueNode hub = createReadHub(graph, loadHub.getValue(), loadHub.getGuard());
+        ValueNode hub = createReadHub(graph, loadHub.getValue(), loadHub.getGuard(), tool);
         graph.replaceFloating(loadHub, hub);
     }
 
@@ -672,9 +675,9 @@
         return value;
     }
 
-    protected abstract ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard);
+    protected abstract ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard, LoweringTool tool);
 
-    protected abstract ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor);
+    protected abstract ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor, LoweringTool tool);
 
     protected PiNode getBoundsCheckedIndex(AccessIndexedNode n, LoweringTool tool, GuardingNode[] nullCheckReturn) {
         StructuredGraph graph = n.graph();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java	Mon Jul 20 11:21:28 2015 -0700
@@ -127,7 +127,7 @@
         Registration r = new Registration(plugins, Array.class);
         r.register2("newInstance", Class.class, int.class, new InvocationPlugin() {
             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unused, ValueNode componentType, ValueNode length) {
-                b.addPush(Kind.Object, new DynamicNewArrayNode(componentType, length, true, null));
+                b.addPush(Kind.Object, new DynamicNewArrayNode(componentType, length, true));
                 return true;
             }
         });
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectType.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectType.java	Mon Jul 20 11:21:28 2015 -0700
@@ -88,6 +88,8 @@
 
     long prototypeMarkWord();
 
+    int layoutHelper();
+
     HotSpotResolvedObjectType getEnclosingType();
 
     ResolvedJavaMethod getClassInitializer();
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java	Mon Jul 20 11:21:28 2015 -0700
@@ -430,7 +430,7 @@
         assert !isInterface();
 
         HotSpotVMConfig config = runtime().getConfig();
-        final int layoutHelper = unsafe.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
+        final int layoutHelper = layoutHelper();
         assert layoutHelper > config.klassLayoutHelperNeutralValue : "must be instance";
 
         // See: Klass::layout_helper_size_in_bytes
@@ -442,6 +442,11 @@
         return needsSlowPath ? -size : size;
     }
 
+    public int layoutHelper() {
+        HotSpotVMConfig config = runtime().getConfig();
+        return unsafe.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
+    }
+
     public synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
         HotSpotResolvedJavaMethod method = null;
         if (methodCache == null) {
--- a/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/NamedLocationIdentity.java	Mon Jul 20 17:01:45 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/NamedLocationIdentity.java	Mon Jul 20 11:21:28 2015 -0700
@@ -29,18 +29,17 @@
 /**
  * A {@link LocationIdentity} with a name.
  */
-public final class NamedLocationIdentity extends LocationIdentity implements FormatWithToString {
+public class NamedLocationIdentity extends LocationIdentity implements FormatWithToString {
 
     /**
      * Map for asserting all {@link NamedLocationIdentity} instances have a unique name.
      */
     static class DB {
-        private static final HashMap<String, NamedLocationIdentity> map = new HashMap<>();
+        private static final HashSet<String> map = new HashSet<>();
 
-        static boolean checkUnique(NamedLocationIdentity identity) {
-            NamedLocationIdentity oldValue = map.put(identity.name, identity);
-            if (oldValue != null) {
-                throw new AssertionError("identity " + identity + " already exists");
+        static boolean checkUnique(String name) {
+            if (!map.add(name)) {
+                throw new AssertionError("identity " + name + " already exists");
             }
             return true;
         }
@@ -49,9 +48,10 @@
     private final String name;
     private final boolean immutable;
 
-    private NamedLocationIdentity(String name, boolean immutable) {
+    protected NamedLocationIdentity(String name, boolean immutable) {
         this.name = name;
         this.immutable = immutable;
+        assert DB.checkUnique(name);
     }
 
     /**
@@ -82,9 +82,7 @@
      * @param immutable true if the location is immutable
      */
     private static NamedLocationIdentity create(String name, boolean immutable) {
-        NamedLocationIdentity id = new NamedLocationIdentity(name, immutable);
-        assert DB.checkUnique(id);
-        return id;
+        return new NamedLocationIdentity(name, immutable);
     }
 
     @Override