src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java
changeset 52033 d6aa9ea2405d
parent 51736 42d99cb7f50f
child 52578 7dd81e82d083
equal deleted inserted replaced
52032:2f7a2e7c3221 52033:d6aa9ea2405d
    22  */
    22  */
    23 
    23 
    24 
    24 
    25 package org.graalvm.compiler.hotspot.replacements;
    25 package org.graalvm.compiler.hotspot.replacements;
    26 
    26 
       
    27 import static jdk.vm.ci.meta.DeoptimizationAction.None;
       
    28 import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
    27 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
    29 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
    28 import static org.graalvm.compiler.core.common.calc.UnsignedMath.belowThan;
    30 import static org.graalvm.compiler.core.common.calc.UnsignedMath.belowThan;
    29 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
    31 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
       
    32 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_ARRAY;
       
    33 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_ARRAY_OR_NULL;
       
    34 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE;
       
    35 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE_OR_NULL;
       
    36 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY;
       
    37 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY_OR_NULL;
    30 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_ARRAY_KLASS_LOCATION;
    38 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_ARRAY_KLASS_LOCATION;
    31 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION;
    39 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION;
    32 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION;
    40 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION;
    33 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION;
    41 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION;
    34 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_END_LOCATION;
    42 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_END_LOCATION;
    68 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
    76 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
    69 import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring;
    77 import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring;
    70 import static org.graalvm.compiler.replacements.nodes.ExplodeLoopNode.explodeLoop;
    78 import static org.graalvm.compiler.replacements.nodes.ExplodeLoopNode.explodeLoop;
    71 
    79 
    72 import org.graalvm.compiler.api.replacements.Fold;
    80 import org.graalvm.compiler.api.replacements.Fold;
       
    81 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
    73 import org.graalvm.compiler.api.replacements.Snippet;
    82 import org.graalvm.compiler.api.replacements.Snippet;
    74 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
    83 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
    75 import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter;
    84 import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter;
    76 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
    85 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
    77 import org.graalvm.compiler.core.common.type.StampFactory;
    86 import org.graalvm.compiler.core.common.type.StampFactory;
    78 import org.graalvm.compiler.debug.DebugHandlersFactory;
    87 import org.graalvm.compiler.debug.DebugHandlersFactory;
    79 import org.graalvm.compiler.debug.GraalError;
    88 import org.graalvm.compiler.debug.GraalError;
    80 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
    89 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
    81 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
    90 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
    82 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
    91 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
    83 import org.graalvm.compiler.hotspot.HotSpotBackend;
       
    84 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
    92 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
    85 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
    93 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
    86 import org.graalvm.compiler.hotspot.nodes.DimensionsNode;
    94 import org.graalvm.compiler.hotspot.nodes.DimensionsNode;
    87 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode;
    95 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode;
    88 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode;
    96 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode;
   124 import jdk.vm.ci.code.CodeUtil;
   132 import jdk.vm.ci.code.CodeUtil;
   125 import jdk.vm.ci.code.MemoryBarriers;
   133 import jdk.vm.ci.code.MemoryBarriers;
   126 import jdk.vm.ci.code.Register;
   134 import jdk.vm.ci.code.Register;
   127 import jdk.vm.ci.code.TargetDescription;
   135 import jdk.vm.ci.code.TargetDescription;
   128 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
   136 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
   129 import jdk.vm.ci.meta.DeoptimizationAction;
       
   130 import jdk.vm.ci.meta.DeoptimizationReason;
       
   131 import jdk.vm.ci.meta.JavaKind;
   137 import jdk.vm.ci.meta.JavaKind;
   132 import jdk.vm.ci.meta.ResolvedJavaType;
   138 import jdk.vm.ci.meta.ResolvedJavaType;
   133 
   139 
   134 /**
   140 /**
   135  * Snippets used for implementing NEW, ANEWARRAY and NEWARRAY.
   141  * Snippets used for implementing NEW, ANEWARRAY and NEWARRAY.
   218             result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, counters);
   224             result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, counters);
   219         } else {
   225         } else {
   220             if (counters != null && counters.stub != null) {
   226             if (counters != null && counters.stub != null) {
   221                 counters.stub.inc();
   227                 counters.stub.inc();
   222             }
   228             }
   223             result = newInstance(HotSpotBackend.NEW_INSTANCE, hub);
   229             result = newInstanceStub(hub);
   224         }
   230         }
   225         profileAllocation("instance", size, typeContext, options);
   231         profileAllocation("instance", size, typeContext, options);
   226         return verifyOop(result);
   232         return verifyOop(result);
   227     }
   233     }
   228 
   234 
       
   235     public static Object newInstanceStub(KlassPointer hub) {
       
   236         if (useNullAllocationStubs(INJECTED_VMCONFIG)) {
       
   237             return nonNullOrDeopt(newInstanceOrNull(NEW_INSTANCE_OR_NULL, hub));
       
   238         } else {
       
   239             return newInstance(NEW_INSTANCE, hub);
       
   240         }
       
   241     }
       
   242 
   229     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
   243     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
   230     public static native Object newInstance(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub);
   244     private static native Object newInstance(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub);
       
   245 
       
   246     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = false)
       
   247     private static native Object newInstanceOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub);
   231 
   248 
   232     @Snippet
   249     @Snippet
   233     public static Object allocateInstancePIC(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
   250     public static Object allocateInstancePIC(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
   234                     @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options,
   251                     @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options,
   235                     @ConstantParameter Counters counters) {
   252                     @ConstantParameter Counters counters) {
   242 
   259 
   243     @Snippet
   260     @Snippet
   244     public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
   261     public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
   245                     @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
   262                     @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
   246         if (probability(SLOW_PATH_PROBABILITY, type == null)) {
   263         if (probability(SLOW_PATH_PROBABILITY, type == null)) {
   247             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
   264             DeoptimizeNode.deopt(None, RuntimeConstraint);
   248         }
   265         }
   249         Class<?> nonNullType = PiNode.piCastNonNullClass(type, SnippetAnchorNode.anchor());
   266         Class<?> nonNullType = PiNode.piCastNonNullClass(type, SnippetAnchorNode.anchor());
   250 
   267 
   251         if (probability(SLOW_PATH_PROBABILITY, DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) {
   268         if (probability(SLOW_PATH_PROBABILITY, DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) {
   252             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
   269             DeoptimizeNode.deopt(None, RuntimeConstraint);
   253         }
   270         }
   254 
   271 
   255         return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, options, counters, nonNullType));
   272         return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(fillContents, threadRegister, options, counters, nonNullType));
   256     }
   273     }
   257 
   274 
   258     private static Object allocateInstanceDynamicHelper(Class<?> type, boolean fillContents, Register threadRegister, OptionValues options, Counters counters, Class<?> nonNullType) {
   275     private static Object allocateInstanceDynamicHelper(boolean fillContents, Register threadRegister, OptionValues options, Counters counters, Class<?> nonNullType) {
   259         KlassPointer hub = ClassGetHubNode.readClass(nonNullType);
   276         KlassPointer hub = ClassGetHubNode.readClass(nonNullType);
   260         if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) {
   277         if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) {
   261             KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor());
   278             KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor());
   262 
   279 
   263             if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(nonNullHub))) {
   280             if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(nonNullHub))) {
   275                      * binding of parameters is not yet supported by the GraphBuilderPlugin system.
   292                      * binding of parameters is not yet supported by the GraphBuilderPlugin system.
   276                      */
   293                      */
   277                     return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", options, counters);
   294                     return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", options, counters);
   278                 }
   295                 }
   279             } else {
   296             } else {
   280                 DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
   297                 DeoptimizeNode.deopt(None, RuntimeConstraint);
   281             }
   298             }
   282         }
   299         }
   283         return dynamicNewInstanceStub(type);
   300         DeoptimizeNode.deopt(None, RuntimeConstraint);
       
   301         return null;
   284     }
   302     }
   285 
   303 
   286     /**
   304     /**
   287      * Maximum array length for which fast path allocation is used.
   305      * Maximum array length for which fast path allocation is used.
   288      */
   306      */
   305         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
   323         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
   306         return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
   324         return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
   307     }
   325     }
   308 
   326 
   309     @Snippet
   327     @Snippet
   310     public static Object allocateArray(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
   328     public static Object allocateArray(KlassPointer hub,
   311                     @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext,
   329                     int length,
   312                     @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
   330                     Word prototypeMarkWord,
       
   331                     @ConstantParameter int headerSize,
       
   332                     @ConstantParameter int log2ElementSize,
       
   333                     @ConstantParameter boolean fillContents,
       
   334                     @ConstantParameter Register threadRegister,
       
   335                     @ConstantParameter boolean maybeUnroll,
       
   336                     @ConstantParameter String typeContext,
       
   337                     @ConstantParameter OptionValues options,
       
   338                     @ConstantParameter Counters counters) {
   313         Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
   339         Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
   314         return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
   340         return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
       
   341     }
       
   342 
       
   343     /**
       
   344      * When allocating on the slow path, determines whether to use a version of the runtime call
       
   345      * that returns {@code null} on a failed allocation instead of raising an OutOfMemoryError.
       
   346      */
       
   347     @Fold
       
   348     static boolean useNullAllocationStubs(@InjectedParameter GraalHotSpotVMConfig config) {
       
   349         return config.areNullAllocationStubsAvailable();
   315     }
   350     }
   316 
   351 
   317     private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister,
   352     private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister,
   318                     boolean maybeUnroll, String typeContext, boolean skipNegativeCheck, OptionValues options, Counters counters) {
   353                     boolean maybeUnroll, String typeContext, boolean skipNegativeCheck, OptionValues options, Counters counters) {
   319         Object result;
   354         Object result;
   329             if (counters != null && counters.arrayLoopInit != null) {
   364             if (counters != null && counters.arrayLoopInit != null) {
   330                 counters.arrayLoopInit.inc();
   365                 counters.arrayLoopInit.inc();
   331             }
   366             }
   332             result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, counters);
   367             result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, counters);
   333         } else {
   368         } else {
   334             result = newArray(HotSpotBackend.NEW_ARRAY, hub, length);
   369             result = newArrayStub(hub, length);
   335         }
   370         }
   336         profileAllocation("array", allocationSize, typeContext, options);
   371         profileAllocation("array", allocationSize, typeContext, options);
   337         return result;
   372         return result;
   338     }
   373     }
   339 
   374 
       
   375     public static Object newArrayStub(KlassPointer hub, int length) {
       
   376         if (useNullAllocationStubs(INJECTED_VMCONFIG)) {
       
   377             return nonNullOrDeopt(newArrayOrNull(NEW_ARRAY_OR_NULL, hub, length));
       
   378         } else {
       
   379             return newArray(NEW_ARRAY, hub, length);
       
   380         }
       
   381     }
       
   382 
   340     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
   383     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
   341     public static native Object newArray(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length);
   384     private static native Object newArray(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length);
   342 
   385 
   343     public static final ForeignCallDescriptor DYNAMIC_NEW_ARRAY = new ForeignCallDescriptor("dynamic_new_array", Object.class, Class.class, int.class);
   386     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = false)
   344     public static final ForeignCallDescriptor DYNAMIC_NEW_INSTANCE = new ForeignCallDescriptor("dynamic_new_instance", Object.class, Class.class);
   387     private static native Object newArrayOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length);
       
   388 
       
   389     /**
       
   390      * Deoptimizes if {@code obj == null} otherwise returns {@code obj}.
       
   391      */
       
   392     private static Object nonNullOrDeopt(Object obj) {
       
   393         if (obj == null) {
       
   394             DeoptimizeNode.deopt(None, RuntimeConstraint);
       
   395         }
       
   396         return obj;
       
   397     }
   345 
   398 
   346     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
   399     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
   347     public static native Object dynamicNewArrayStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType, int length);
   400     public static native Object dynamicNewInstance(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
   348 
   401 
   349     public static Object dynamicNewInstanceStub(Class<?> elementType) {
   402     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = false)
   350         return dynamicNewInstanceStubCall(DYNAMIC_NEW_INSTANCE, elementType);
   403     public static native Object dynamicNewInstanceOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
   351     }
       
   352 
       
   353     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
       
   354     public static native Object dynamicNewInstanceStubCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
       
   355 
   404 
   356     @Snippet
   405     @Snippet
   357     public static Object allocateArrayDynamic(Class<?> elementType, Class<?> voidClass, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
   406     public static Object allocateArrayDynamic(Class<?> elementType, Class<?> voidClass, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
   358                     @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord, @ConstantParameter OptionValues options,
   407                     @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord, @ConstantParameter OptionValues options,
   359                     @ConstantParameter Counters counters) {
   408                     @ConstantParameter Counters counters) {
   367          * We only need the dynamic check for void when we have no static information from
   416          * We only need the dynamic check for void when we have no static information from
   368          * knownElementKind.
   417          * knownElementKind.
   369          */
   418          */
   370         staticAssert(knownElementKind != JavaKind.Void, "unsupported knownElementKind");
   419         staticAssert(knownElementKind != JavaKind.Void, "unsupported knownElementKind");
   371         if (knownElementKind == JavaKind.Illegal && probability(SLOW_PATH_PROBABILITY, elementType == null || DynamicNewArrayNode.throwsIllegalArgumentException(elementType, voidClass))) {
   420         if (knownElementKind == JavaKind.Illegal && probability(SLOW_PATH_PROBABILITY, elementType == null || DynamicNewArrayNode.throwsIllegalArgumentException(elementType, voidClass))) {
   372             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
   421             DeoptimizeNode.deopt(None, RuntimeConstraint);
   373         }
   422         }
   374 
   423 
   375         KlassPointer klass = loadKlassFromObject(elementType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION);
   424         KlassPointer klass = loadKlassFromObject(elementType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION);
   376         if (klass.isNull()) {
   425         if (klass.isNull()) {
   377             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
   426             DeoptimizeNode.deopt(None, RuntimeConstraint);
   378         }
   427         }
   379         KlassPointer nonNullKlass = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor());
   428         KlassPointer nonNullKlass = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor());
   380 
   429 
   381         if (length < 0) {
   430         if (length < 0) {
   382             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
   431             DeoptimizeNode.deopt(None, RuntimeConstraint);
   383         }
   432         }
   384         int layoutHelper;
   433         int layoutHelper;
   385         if (knownElementKind == JavaKind.Illegal) {
   434         if (knownElementKind == JavaKind.Illegal) {
   386             layoutHelper = readLayoutHelper(nonNullKlass);
   435             layoutHelper = readLayoutHelper(nonNullKlass);
   387         } else {
   436         } else {
   410 
   459 
   411     /**
   460     /**
   412      * Calls the runtime stub for implementing MULTIANEWARRAY.
   461      * Calls the runtime stub for implementing MULTIANEWARRAY.
   413      */
   462      */
   414     @Snippet
   463     @Snippet
   415     public static Object newmultiarray(KlassPointer hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) {
   464     private static Object newmultiarray(KlassPointer hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) {
   416         Word dims = DimensionsNode.allocaDimsArray(rank);
   465         Word dims = DimensionsNode.allocaDimsArray(rank);
   417         ExplodeLoopNode.explodeLoop();
   466         ExplodeLoopNode.explodeLoop();
   418         for (int i = 0; i < rank; i++) {
   467         for (int i = 0; i < rank; i++) {
   419             dims.writeInt(i * 4, dimensions[i], LocationIdentity.init());
   468             dims.writeInt(i * 4, dimensions[i], LocationIdentity.init());
   420         }
   469         }
   421         return newArrayCall(HotSpotBackend.NEW_MULTI_ARRAY, hub, rank, dims);
   470         return newMultiArrayStub(hub, rank, dims);
   422     }
   471     }
   423 
   472 
   424     @Snippet
   473     private static Object newMultiArrayStub(KlassPointer hub, int rank, Word dims) {
   425     public static Object newmultiarrayPIC(KlassPointer hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) {
   474         if (useNullAllocationStubs(INJECTED_VMCONFIG)) {
       
   475             return nonNullOrDeopt(newMultiArrayOrNull(NEW_MULTI_ARRAY_OR_NULL, hub, rank, dims));
       
   476         } else {
       
   477             return newMultiArray(NEW_MULTI_ARRAY, hub, rank, dims);
       
   478         }
       
   479     }
       
   480 
       
   481     @Snippet
       
   482     private static Object newmultiarrayPIC(KlassPointer hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) {
   426         // Array type would be resolved by dominating resolution.
   483         // Array type would be resolved by dominating resolution.
   427         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
   484         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
   428         return newmultiarray(picHub, rank, dimensions);
   485         return newmultiarray(picHub, rank, dimensions);
   429     }
   486     }
   430 
   487 
   431     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
   488     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
   432     public static native Object newArrayCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int rank, Word dims);
   489     private static native Object newMultiArray(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int rank, Word dims);
       
   490 
       
   491     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = false)
       
   492     private static native Object newMultiArrayOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int rank, Word dims);
   433 
   493 
   434     /**
   494     /**
   435      * Maximum number of long stores to emit when zeroing an object with a constant size. Larger
   495      * Maximum number of long stores to emit when zeroing an object with a constant size. Larger
   436      * objects have their bodies initialized in a loop.
   496      * objects have their bodies initialized in a loop.
   437      */
   497      */
   507     private static void fillWithGarbage(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) {
   567     private static void fillWithGarbage(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) {
   508         fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, counters);
   568         fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, counters);
   509     }
   569     }
   510 
   570 
   511     /**
   571     /**
   512      * Formats some allocated memory with an object header and zeroes out the rest. Disables asserts
       
   513      * since they can't be compiled in stubs.
       
   514      */
       
   515     public static Object formatObjectForStub(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord) {
       
   516         return formatObject(hub, size, memory, compileTimePrototypeMarkWord, true, false, null);
       
   517     }
       
   518 
       
   519     /**
       
   520      * Formats some allocated memory with an object header and zeroes out the rest.
   572      * Formats some allocated memory with an object header and zeroes out the rest.
   521      */
   573      */
   522     protected static Object formatObject(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, Counters counters) {
   574     private static Object formatObject(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, Counters counters) {
   523         Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord;
   575         Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord;
   524         initializeObjectHeader(memory, prototypeMarkWord, hub);
   576         initializeObjectHeader(memory, prototypeMarkWord, hub);
   525         if (fillContents) {
   577         if (fillContents) {
   526             zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters);
   578             zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters);
   527         } else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
   579         } else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
   530         MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
   582         MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
   531         return memory.toObjectNonNull();
   583         return memory.toObjectNonNull();
   532     }
   584     }
   533 
   585 
   534     @Snippet
   586     @Snippet
   535     protected static void verifyHeap(@ConstantParameter Register threadRegister) {
   587     private static void verifyHeap(@ConstantParameter Register threadRegister) {
   536         Word thread = registerAsWord(threadRegister);
   588         Word thread = registerAsWord(threadRegister);
   537         Word topValue = readTlabTop(thread);
   589         Word topValue = readTlabTop(thread);
   538         if (!topValue.equal(WordFactory.zero())) {
   590         if (!topValue.equal(WordFactory.zero())) {
   539             Word topValueContents = topValue.readWord(0, MARK_WORD_LOCATION);
   591             Word topValueContents = topValue.readWord(0, MARK_WORD_LOCATION);
   540             if (topValueContents.equal(WordFactory.zero())) {
   592             if (topValueContents.equal(WordFactory.zero())) {
   544     }
   596     }
   545 
   597 
   546     /**
   598     /**
   547      * Formats some allocated memory with an object header and zeroes out the rest.
   599      * Formats some allocated memory with an object header and zeroes out the rest.
   548      */
   600      */
   549     public static Object formatArray(KlassPointer hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll,
   601     private static Object formatArray(KlassPointer hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll,
   550                     Counters counters) {
   602                     Counters counters) {
   551         memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init());
   603         memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init());
   552         /*
   604         /*
   553          * store hub last as the concurrent garbage collectors assume length is valid if hub field
   605          * store hub last as the concurrent garbage collectors assume length is valid if hub field
   554          * is not null
   606          * is not null