# HG changeset patch # User Tom Rodriguez # Date 1437416299 25200 # Node ID efeabef8df701e6509a329077fd0c0fcc58ada7e # Parent 2fbb9ce20d7df8283763266713c89b3b86815fc3 Improve DynamicNewArrayNode code generation diff -r 2fbb9ce20d7d -r efeabef8df70 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- 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(); diff -r 2fbb9ce20d7d -r efeabef8df70 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java --- 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 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 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; diff -r 2fbb9ce20d7d -r efeabef8df70 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- 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; } }); diff -r 2fbb9ce20d7d -r efeabef8df70 jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectType.java --- 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(); diff -r 2fbb9ce20d7d -r efeabef8df70 jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java --- 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) {