changeset 22256:efeabef8df70

Improve DynamicNewArrayNode code generation
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Mon, 20 Jul 2015 11:18:19 -0700
parents 2fbb9ce20d7d
children 565196752144
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectType.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java
diffstat 5 files changed, 52 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Jul 20 11:18:04 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Jul 20 11:18:19 2015 -0700
@@ -197,7 +197,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 +220,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 +241,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 +256,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 = KlassPointer.fromWord(loadWordFromObject(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 +276,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());
     }
 
     /**
@@ -479,6 +483,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 +520,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();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Mon Jul 20 11:18:04 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Mon Jul 20 11:18:19 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.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java	Mon Jul 20 11:18:04 2015 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java	Mon Jul 20 11:18:19 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 11:18:04 2015 -0700
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectType.java	Mon Jul 20 11:18:19 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 11:18:04 2015 -0700
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java	Mon Jul 20 11:18:19 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) {