src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54724 62f373a53296
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
    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.InvalidateRecompile;
    27 import static jdk.vm.ci.meta.DeoptimizationAction.None;
    28 import static jdk.vm.ci.meta.DeoptimizationAction.None;
    28 import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
    29 import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
    29 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
    30 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
    30 import static org.graalvm.compiler.core.common.GraalOptions.MinimalBulkZeroingSize;
    31 import static org.graalvm.compiler.core.common.GraalOptions.MinimalBulkZeroingSize;
    31 import static org.graalvm.compiler.core.common.calc.UnsignedMath.belowThan;
    32 import static org.graalvm.compiler.core.common.calc.UnsignedMath.belowThan;
    36 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE;
    37 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE;
    37 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE_OR_NULL;
    38 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE_OR_NULL;
    38 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY;
    39 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY;
    39 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY_OR_NULL;
    40 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY_OR_NULL;
    40 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_ARRAY_KLASS_LOCATION;
    41 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_ARRAY_KLASS_LOCATION;
       
    42 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_INIT_STATE_LOCATION;
    41 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION;
    43 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION;
    42 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION;
    44 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION;
    43 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION;
    45 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION;
    44 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_END_LOCATION;
    46 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_END_LOCATION;
    45 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_TOP_LOCATION;
    47 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_TOP_LOCATION;
    51 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayAllocationSize;
    53 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayAllocationSize;
    52 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayKlassOffset;
    54 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayKlassOffset;
    53 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayLengthOffset;
    55 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayLengthOffset;
    54 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.initializeObjectHeader;
    56 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.initializeObjectHeader;
    55 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.instanceHeaderSize;
    57 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.instanceHeaderSize;
       
    58 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.instanceKlassStateBeingInitialized;
    56 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.isInstanceKlassFullyInitialized;
    59 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.isInstanceKlassFullyInitialized;
    57 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperHeaderSizeMask;
    60 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperHeaderSizeMask;
    58 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperHeaderSizeShift;
    61 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperHeaderSizeShift;
    59 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeMask;
    62 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeMask;
    60 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeShift;
    63 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeShift;
    61 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadKlassFromObject;
    64 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadKlassFromObject;
    62 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset;
    65 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset;
       
    66 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readInstanceKlassInitState;
       
    67 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readInstanceKlassInitThread;
    63 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper;
    68 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper;
    64 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readTlabEnd;
    69 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readTlabEnd;
    65 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readTlabTop;
    70 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readTlabTop;
    66 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
    71 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
    67 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useBiasedLocking;
    72 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useBiasedLocking;
    70 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeTlabTop;
    75 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeTlabTop;
    71 import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocations;
    76 import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocations;
    72 import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocationsContext;
    77 import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocationsContext;
    73 import static org.graalvm.compiler.nodes.PiArrayNode.piArrayCastToSnippetReplaceeStamp;
    78 import static org.graalvm.compiler.nodes.PiArrayNode.piArrayCastToSnippetReplaceeStamp;
    74 import static org.graalvm.compiler.nodes.PiNode.piCastToSnippetReplaceeStamp;
    79 import static org.graalvm.compiler.nodes.PiNode.piCastToSnippetReplaceeStamp;
       
    80 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.DEOPT_PROBABILITY;
    75 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY;
    81 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY;
    76 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY;
    82 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY;
    77 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
    83 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
       
    84 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_FAST_PATH_PROBABILITY;
    78 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
    85 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
    79 import static org.graalvm.compiler.replacements.ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED;
    86 import static org.graalvm.compiler.replacements.ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED;
    80 import static org.graalvm.compiler.replacements.ReplacementsUtil.runtimeAssert;
    87 import static org.graalvm.compiler.replacements.ReplacementsUtil.runtimeAssert;
    81 import static org.graalvm.compiler.replacements.ReplacementsUtil.staticAssert;
    88 import static org.graalvm.compiler.replacements.ReplacementsUtil.staticAssert;
    82 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
    89 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
    96 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
   103 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
    97 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
   104 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
    98 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
   105 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
    99 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
   106 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
   100 import org.graalvm.compiler.hotspot.nodes.DimensionsNode;
   107 import org.graalvm.compiler.hotspot.nodes.DimensionsNode;
       
   108 import org.graalvm.compiler.hotspot.nodes.KlassBeingInitializedCheckNode;
   101 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode;
   109 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode;
   102 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode;
   110 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode;
   103 import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
   111 import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
   104 import org.graalvm.compiler.hotspot.word.KlassPointer;
   112 import org.graalvm.compiler.hotspot.word.KlassPointer;
   105 import org.graalvm.compiler.nodes.ConstantNode;
   113 import org.graalvm.compiler.nodes.ConstantNode;
   109 import org.graalvm.compiler.nodes.SnippetAnchorNode;
   117 import org.graalvm.compiler.nodes.SnippetAnchorNode;
   110 import org.graalvm.compiler.nodes.StructuredGraph;
   118 import org.graalvm.compiler.nodes.StructuredGraph;
   111 import org.graalvm.compiler.nodes.ValueNode;
   119 import org.graalvm.compiler.nodes.ValueNode;
   112 import org.graalvm.compiler.nodes.debug.DynamicCounterNode;
   120 import org.graalvm.compiler.nodes.debug.DynamicCounterNode;
   113 import org.graalvm.compiler.nodes.debug.VerifyHeapNode;
   121 import org.graalvm.compiler.nodes.debug.VerifyHeapNode;
       
   122 import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
   114 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
   123 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
   115 import org.graalvm.compiler.nodes.extended.MembarNode;
   124 import org.graalvm.compiler.nodes.extended.MembarNode;
   116 import org.graalvm.compiler.nodes.java.DynamicNewArrayNode;
   125 import org.graalvm.compiler.nodes.java.DynamicNewArrayNode;
   117 import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode;
   126 import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode;
   118 import org.graalvm.compiler.nodes.java.NewArrayNode;
   127 import org.graalvm.compiler.nodes.java.NewArrayNode;
   209             }
   218             }
   210         }
   219         }
   211     }
   220     }
   212 
   221 
   213     @Snippet
   222     @Snippet
   214     public static Object allocateInstance(@ConstantParameter long size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
   223     public static Object allocateInstance(@ConstantParameter long size,
   215                     @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext,
   224                     KlassPointer hub,
       
   225                     Word prototypeMarkWord,
       
   226                     @ConstantParameter boolean fillContents,
       
   227                     @ConstantParameter boolean emitMemoryBarrier,
       
   228                     @ConstantParameter Register threadRegister,
       
   229                     @ConstantParameter boolean constantSize,
       
   230                     @ConstantParameter String typeContext,
   216                     @ConstantParameter Counters counters) {
   231                     @ConstantParameter Counters counters) {
   217         return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, counters));
   232         return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, emitMemoryBarrier, threadRegister, constantSize, typeContext, counters));
   218     }
   233     }
   219 
   234 
   220     public static Object allocateInstanceHelper(long size, KlassPointer hub, Word prototypeMarkWord, boolean fillContents,
   235     public static Object allocateInstanceHelper(long size,
   221                     Register threadRegister, boolean constantSize, String typeContext, Counters counters) {
   236                     KlassPointer hub,
       
   237                     Word prototypeMarkWord,
       
   238                     boolean fillContents,
       
   239                     boolean emitMemoryBarrier,
       
   240                     Register threadRegister,
       
   241                     boolean constantSize,
       
   242                     String typeContext,
       
   243                     Counters counters) {
   222         Object result;
   244         Object result;
   223         Word thread = registerAsWord(threadRegister);
   245         Word thread = registerAsWord(threadRegister);
   224         Word top = readTlabTop(thread);
   246         Word top = readTlabTop(thread);
   225         Word end = readTlabEnd(thread);
   247         Word end = readTlabEnd(thread);
   226         Word newTop = top.add(WordFactory.unsigned(size));
   248         Word newTop = top.add(WordFactory.unsigned(size));
   227         if (useTLAB(INJECTED_VMCONFIG) && probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) {
   249         if (useTLAB(INJECTED_VMCONFIG) && probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) {
   228             writeTlabTop(thread, newTop);
   250             writeTlabTop(thread, newTop);
   229             emitPrefetchAllocate(newTop, false);
   251             emitPrefetchAllocate(newTop, false);
   230             result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, counters);
   252             result = formatObject(hub, size, top, prototypeMarkWord, fillContents, emitMemoryBarrier, constantSize, counters);
   231         } else {
   253         } else {
   232             Counters theCounters = counters;
   254             Counters theCounters = counters;
   233             if (theCounters != null && theCounters.stub != null) {
   255             if (theCounters != null && theCounters.stub != null) {
   234                 theCounters.stub.inc();
   256                 theCounters.stub.inc();
   235             }
   257             }
   252 
   274 
   253     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = false)
   275     @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = false)
   254     private static native Object newInstanceOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub);
   276     private static native Object newInstanceOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub);
   255 
   277 
   256     @Snippet
   278     @Snippet
   257     public static Object allocateInstancePIC(@ConstantParameter long size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
   279     public static Object allocateInstancePIC(@ConstantParameter long size,
   258                     @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext,
   280                     KlassPointer hub,
       
   281                     Word prototypeMarkWord,
       
   282                     @ConstantParameter boolean fillContents,
       
   283                     @ConstantParameter boolean emitMemoryBarrier,
       
   284                     @ConstantParameter Register threadRegister,
       
   285                     @ConstantParameter boolean constantSize,
       
   286                     @ConstantParameter String typeContext,
   259                     @ConstantParameter Counters counters) {
   287                     @ConstantParameter Counters counters) {
   260         // Klass must be initialized by the time the first instance is allocated, therefore we can
   288         // Klass must be initialized by the time the first instance is allocated, therefore we can
   261         // just load it from the corresponding cell and avoid the resolution check. We have to use a
   289         // just load it from the corresponding cell and avoid the resolution check. We have to use a
   262         // fixed load though, to prevent it from floating above the initialization.
   290         // fixed load though, to prevent it from floating above the initialization.
   263         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
   291         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
   264         return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, counters));
   292         return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, emitMemoryBarrier, threadRegister, constantSize, typeContext, counters));
   265     }
   293     }
   266 
   294 
   267     @Snippet
   295     @Snippet
   268     public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
   296     public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass,
       
   297                     @ConstantParameter boolean fillContents,
       
   298                     @ConstantParameter boolean emitMemoryBarrier,
       
   299                     @ConstantParameter Register threadRegister,
   269                     @ConstantParameter Counters counters) {
   300                     @ConstantParameter Counters counters) {
   270         if (probability(SLOW_PATH_PROBABILITY, type == null)) {
   301         if (probability(DEOPT_PROBABILITY, type == null)) {
   271             DeoptimizeNode.deopt(None, RuntimeConstraint);
   302             DeoptimizeNode.deopt(None, RuntimeConstraint);
   272         }
   303         }
   273         Class<?> nonNullType = PiNode.piCastNonNullClass(type, SnippetAnchorNode.anchor());
   304         Class<?> nonNullType = PiNode.piCastNonNullClass(type, SnippetAnchorNode.anchor());
   274 
   305 
   275         if (probability(SLOW_PATH_PROBABILITY, DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) {
   306         if (probability(DEOPT_PROBABILITY, DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) {
   276             DeoptimizeNode.deopt(None, RuntimeConstraint);
   307             DeoptimizeNode.deopt(None, RuntimeConstraint);
   277         }
   308         }
   278 
   309 
   279         return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, counters, nonNullType));
   310         return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, emitMemoryBarrier, threadRegister, counters, nonNullType));
   280     }
   311     }
   281 
   312 
   282     private static Object allocateInstanceDynamicHelper(Class<?> type, boolean fillContents, Register threadRegister, Counters counters, Class<?> nonNullType) {
   313     private static Object allocateInstanceDynamicHelper(Class<?> type,
       
   314                     boolean fillContents,
       
   315                     boolean emitMemoryBarrier,
       
   316                     Register threadRegister,
       
   317                     Counters counters,
       
   318                     Class<?> nonNullType) {
   283         KlassPointer hub = ClassGetHubNode.readClass(nonNullType);
   319         KlassPointer hub = ClassGetHubNode.readClass(nonNullType);
   284         if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) {
   320         if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) {
   285             KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor());
   321             KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor());
   286 
   322 
   287             if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(nonNullHub))) {
   323             if (probability(VERY_FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(nonNullHub))) {
   288                 int layoutHelper = readLayoutHelper(nonNullHub);
   324                 int layoutHelper = readLayoutHelper(nonNullHub);
   289                 /*
   325                 /*
   290                  * src/share/vm/oops/klass.hpp: For instances, layout helper is a positive number,
   326                  * src/share/vm/oops/klass.hpp: For instances, layout helper is a positive number,
   291                  * the instance size. This size is already passed through align_object_size and
   327                  * the instance size. This size is already passed through align_object_size and
   292                  * scaled to bytes. The low order bit is set if instances of this class cannot be
   328                  * scaled to bytes. The low order bit is set if instances of this class cannot be
   296                     Word prototypeMarkWord = nonNullHub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION);
   332                     Word prototypeMarkWord = nonNullHub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION);
   297                     /*
   333                     /*
   298                      * FIXME(je,ds): we should actually pass typeContext instead of "" but late
   334                      * FIXME(je,ds): we should actually pass typeContext instead of "" but late
   299                      * binding of parameters is not yet supported by the GraphBuilderPlugin system.
   335                      * binding of parameters is not yet supported by the GraphBuilderPlugin system.
   300                      */
   336                      */
   301                     return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", counters);
   337                     return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, emitMemoryBarrier, threadRegister, false, "", counters);
   302                 }
   338                 }
   303             } else {
   339             } else {
   304                 DeoptimizeNode.deopt(None, RuntimeConstraint);
   340                 DeoptimizeNode.deopt(None, RuntimeConstraint);
   305             }
   341             }
   306         }
   342         }
   317                     int length,
   353                     int length,
   318                     Word prototypeMarkWord,
   354                     Word prototypeMarkWord,
   319                     @ConstantParameter int headerSize,
   355                     @ConstantParameter int headerSize,
   320                     @ConstantParameter int log2ElementSize,
   356                     @ConstantParameter int log2ElementSize,
   321                     @ConstantParameter boolean fillContents,
   357                     @ConstantParameter boolean fillContents,
       
   358                     @ConstantParameter boolean emitMemoryBarrier,
   322                     @ConstantParameter Register threadRegister,
   359                     @ConstantParameter Register threadRegister,
   323                     @ConstantParameter boolean maybeUnroll,
   360                     @ConstantParameter boolean maybeUnroll,
   324                     @ConstantParameter String typeContext,
   361                     @ConstantParameter String typeContext,
   325                     @ConstantParameter boolean useBulkZeroing,
   362                     @ConstantParameter boolean supportsBulkZeroing,
   326                     @ConstantParameter Counters counters) {
   363                     @ConstantParameter Counters counters) {
   327         // Primitive array types are eagerly pre-resolved. We can use a floating load.
   364         // Primitive array types are eagerly pre-resolved. We can use a floating load.
   328         KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub);
   365         KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub);
   329         return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
   366         return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
   330                         threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters);
   367                         emitMemoryBarrier, threadRegister, maybeUnroll, typeContext, supportsBulkZeroing, counters);
   331     }
   368     }
   332 
   369 
   333     @Snippet
   370     @Snippet
   334     public static Object allocateArrayPIC(KlassPointer hub,
   371     public static Object allocateArrayPIC(KlassPointer hub,
   335                     int length,
   372                     int length,
   336                     Word prototypeMarkWord,
   373                     Word prototypeMarkWord,
   337                     @ConstantParameter int headerSize,
   374                     @ConstantParameter int headerSize,
   338                     @ConstantParameter int log2ElementSize,
   375                     @ConstantParameter int log2ElementSize,
   339                     @ConstantParameter boolean fillContents,
   376                     @ConstantParameter boolean fillContents,
       
   377                     @ConstantParameter boolean emitMemoryBarrier,
   340                     @ConstantParameter Register threadRegister,
   378                     @ConstantParameter Register threadRegister,
   341                     @ConstantParameter boolean maybeUnroll,
   379                     @ConstantParameter boolean maybeUnroll,
   342                     @ConstantParameter String typeContext,
   380                     @ConstantParameter String typeContext,
   343                     @ConstantParameter boolean useBulkZeroing,
   381                     @ConstantParameter boolean supportsBulkZeroing,
   344                     @ConstantParameter Counters counters) {
   382                     @ConstantParameter Counters counters) {
   345         // Array type would be resolved by dominating resolution.
   383         // Array type would be resolved by dominating resolution.
   346         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
   384         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
   347         return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
   385         return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
   348                         threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters);
   386                         emitMemoryBarrier, threadRegister, maybeUnroll, typeContext, supportsBulkZeroing, counters);
   349     }
   387     }
   350 
   388 
   351     @Snippet
   389     @Snippet
   352     public static Object allocateArray(KlassPointer hub,
   390     public static Object allocateArray(KlassPointer hub,
   353                     int length,
   391                     int length,
   354                     Word prototypeMarkWord,
   392                     Word prototypeMarkWord,
   355                     @ConstantParameter int headerSize,
   393                     @ConstantParameter int headerSize,
   356                     @ConstantParameter int log2ElementSize,
   394                     @ConstantParameter int log2ElementSize,
   357                     @ConstantParameter boolean fillContents,
   395                     @ConstantParameter boolean fillContents,
       
   396                     @ConstantParameter boolean emitMemoryBarrier,
   358                     @ConstantParameter Register threadRegister,
   397                     @ConstantParameter Register threadRegister,
   359                     @ConstantParameter boolean maybeUnroll,
   398                     @ConstantParameter boolean maybeUnroll,
   360                     @ConstantParameter String typeContext,
   399                     @ConstantParameter String typeContext,
   361                     @ConstantParameter boolean useBulkZeroing,
   400                     @ConstantParameter boolean supportsBulkZeroing,
   362                     @ConstantParameter Counters counters) {
   401                     @ConstantParameter Counters counters) {
   363         Object result = allocateArrayImpl(hub,
   402         Object result = allocateArrayImpl(hub,
   364                         length,
   403                         length,
   365                         prototypeMarkWord,
   404                         prototypeMarkWord,
   366                         headerSize,
   405                         headerSize,
   367                         log2ElementSize,
   406                         log2ElementSize,
   368                         fillContents,
   407                         fillContents,
   369                         threadRegister,
   408                         emitMemoryBarrier, threadRegister,
   370                         maybeUnroll,
   409                         maybeUnroll,
   371                         typeContext,
   410                         typeContext,
   372                         useBulkZeroing,
   411                         supportsBulkZeroing,
   373                         counters);
   412                         counters);
   374         return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
   413         return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
   375     }
   414     }
   376 
   415 
   377     /**
   416     /**
   381     @Fold
   420     @Fold
   382     static boolean useNullAllocationStubs(@InjectedParameter GraalHotSpotVMConfig config) {
   421     static boolean useNullAllocationStubs(@InjectedParameter GraalHotSpotVMConfig config) {
   383         return config.areNullAllocationStubsAvailable();
   422         return config.areNullAllocationStubsAvailable();
   384     }
   423     }
   385 
   424 
   386     private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister,
   425     private static Object allocateArrayImpl(KlassPointer hub,
   387                     boolean maybeUnroll, String typeContext, boolean useBulkZeroing, Counters counters) {
   426                     int length,
       
   427                     Word prototypeMarkWord,
       
   428                     int headerSize,
       
   429                     int log2ElementSize,
       
   430                     boolean fillContents,
       
   431                     boolean emitMemoryBarrier,
       
   432                     Register threadRegister,
       
   433                     boolean maybeUnroll,
       
   434                     String typeContext,
       
   435                     boolean supportsBulkZeroing,
       
   436                     Counters counters) {
   388         Object result;
   437         Object result;
   389         long allocationSize = arrayAllocationSize(length, headerSize, log2ElementSize);
   438         long allocationSize = arrayAllocationSize(length, headerSize, log2ElementSize);
   390         Word thread = registerAsWord(threadRegister);
   439         Word thread = registerAsWord(threadRegister);
   391         Word top = readTlabTop(thread);
   440         Word top = readTlabTop(thread);
   392         Word end = readTlabEnd(thread);
   441         Word end = readTlabEnd(thread);
   397             emitPrefetchAllocate(newTop, true);
   446             emitPrefetchAllocate(newTop, true);
   398             Counters theCounters = counters;
   447             Counters theCounters = counters;
   399             if (theCounters != null && theCounters.arrayLoopInit != null) {
   448             if (theCounters != null && theCounters.arrayLoopInit != null) {
   400                 theCounters.arrayLoopInit.inc();
   449                 theCounters.arrayLoopInit.inc();
   401             }
   450             }
   402             result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, useBulkZeroing, counters);
   451             result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, emitMemoryBarrier, maybeUnroll, supportsBulkZeroing, counters);
   403         } else {
   452         } else {
   404             result = newArrayStub(hub, length);
   453             result = newArrayStub(hub, length);
   405         }
   454         }
   406         profileAllocation("array", allocationSize, typeContext);
   455         profileAllocation("array", allocationSize, typeContext);
   407         return result;
   456         return result;
   441 
   490 
   442     /**
   491     /**
   443      * Deoptimizes if {@code obj == null} otherwise returns {@code obj}.
   492      * Deoptimizes if {@code obj == null} otherwise returns {@code obj}.
   444      */
   493      */
   445     private static Object nonNullOrDeopt(Object obj) {
   494     private static Object nonNullOrDeopt(Object obj) {
   446         if (obj == null) {
   495         if (BranchProbabilityNode.probability(BranchProbabilityNode.DEOPT_PROBABILITY, obj == null)) {
   447             DeoptimizeNode.deopt(None, RuntimeConstraint);
   496             DeoptimizeNode.deopt(None, RuntimeConstraint);
   448         }
   497         }
   449         return obj;
   498         return obj;
   450     }
   499     }
   451 
   500 
   458     @Snippet
   507     @Snippet
   459     public static Object allocateArrayDynamic(Class<?> elementType,
   508     public static Object allocateArrayDynamic(Class<?> elementType,
   460                     Class<?> voidClass,
   509                     Class<?> voidClass,
   461                     int length,
   510                     int length,
   462                     @ConstantParameter boolean fillContents,
   511                     @ConstantParameter boolean fillContents,
       
   512                     @ConstantParameter boolean emitMemoryBarrier,
   463                     @ConstantParameter Register threadRegister,
   513                     @ConstantParameter Register threadRegister,
   464                     @ConstantParameter JavaKind knownElementKind,
   514                     @ConstantParameter JavaKind knownElementKind,
   465                     @ConstantParameter int knownLayoutHelper,
   515                     @ConstantParameter int knownLayoutHelper,
   466                     @ConstantParameter boolean useBulkZeroing,
   516                     @ConstantParameter boolean supportsBulkZeroing,
   467                     Word prototypeMarkWord,
   517                     Word prototypeMarkWord,
   468                     @ConstantParameter Counters counters) {
   518                     @ConstantParameter Counters counters) {
   469         Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind,
   519         Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, emitMemoryBarrier, threadRegister, knownElementKind,
   470                         knownLayoutHelper, useBulkZeroing, prototypeMarkWord, counters);
   520                         knownLayoutHelper, supportsBulkZeroing, prototypeMarkWord, counters);
   471         return result;
   521         return result;
   472     }
   522     }
   473 
   523 
   474     private static Object allocateArrayDynamicImpl(Class<?> elementType, Class<?> voidClass, int length, boolean fillContents, Register threadRegister, JavaKind knownElementKind,
   524     private static Object allocateArrayDynamicImpl(Class<?> elementType,
   475                     int knownLayoutHelper, boolean useBulkZeroing, Word prototypeMarkWord, Counters counters) {
   525                     Class<?> voidClass,
       
   526                     int length,
       
   527                     boolean fillContents,
       
   528                     boolean emitMemoryBarrier,
       
   529                     Register threadRegister,
       
   530                     JavaKind knownElementKind,
       
   531                     int knownLayoutHelper,
       
   532                     boolean supportsBulkZeroing,
       
   533                     Word prototypeMarkWord,
       
   534                     Counters counters) {
   476         /*
   535         /*
   477          * We only need the dynamic check for void when we have no static information from
   536          * We only need the dynamic check for void when we have no static information from
   478          * knownElementKind.
   537          * knownElementKind.
   479          */
   538          */
   480         staticAssert(knownElementKind != JavaKind.Void, "unsupported knownElementKind");
   539         staticAssert(knownElementKind != JavaKind.Void, "unsupported knownElementKind");
   481         if (knownElementKind == JavaKind.Illegal && probability(SLOW_PATH_PROBABILITY, elementType == null || DynamicNewArrayNode.throwsIllegalArgumentException(elementType, voidClass))) {
   540         if (knownElementKind == JavaKind.Illegal && probability(SLOW_PATH_PROBABILITY, elementType == null || DynamicNewArrayNode.throwsIllegalArgumentException(elementType, voidClass))) {
   482             DeoptimizeNode.deopt(None, RuntimeConstraint);
   541             DeoptimizeNode.deopt(None, RuntimeConstraint);
   483         }
   542         }
   484 
   543 
   485         KlassPointer klass = loadKlassFromObject(elementType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION);
   544         KlassPointer klass = loadKlassFromObject(elementType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION);
   486         if (klass.isNull()) {
   545         if (probability(DEOPT_PROBABILITY, klass.isNull())) {
   487             DeoptimizeNode.deopt(None, RuntimeConstraint);
   546             DeoptimizeNode.deopt(None, RuntimeConstraint);
   488         }
   547         }
   489         KlassPointer nonNullKlass = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor());
   548         KlassPointer nonNullKlass = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor());
   490 
   549 
   491         if (length < 0) {
   550         if (probability(DEOPT_PROBABILITY, length < 0)) {
   492             DeoptimizeNode.deopt(None, RuntimeConstraint);
   551             DeoptimizeNode.deopt(None, RuntimeConstraint);
   493         }
   552         }
   494         int layoutHelper;
   553         int layoutHelper;
   495         if (knownElementKind == JavaKind.Illegal) {
   554         if (knownElementKind == JavaKind.Illegal) {
   496             layoutHelper = readLayoutHelper(nonNullKlass);
   555             layoutHelper = readLayoutHelper(nonNullKlass);
   513 
   572 
   514         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG);
   573         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG);
   515         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
   574         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
   516 
   575 
   517         Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
   576         Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
   518                         threadRegister, false, "dynamic type", useBulkZeroing, counters);
   577                         emitMemoryBarrier, threadRegister, false, "dynamic type", supportsBulkZeroing, counters);
   519         return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
   578         return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
   520     }
   579     }
   521 
   580 
   522     /**
   581     /**
   523      * Calls the runtime stub for implementing MULTIANEWARRAY.
   582      * Calls the runtime stub for implementing MULTIANEWARRAY.
   561 
   620 
   562     /**
   621     /**
   563      * Zero uninitialized memory in a newly allocated object, unrolling as necessary and ensuring
   622      * Zero uninitialized memory in a newly allocated object, unrolling as necessary and ensuring
   564      * that stores are aligned.
   623      * that stores are aligned.
   565      *
   624      *
   566      * @param size number of bytes to zero
       
   567      * @param memory beginning of object which is being zeroed
   625      * @param memory beginning of object which is being zeroed
   568      * @param constantSize is {@code size} known to be constant in the snippet
   626      * @param startOffset offset to begin zeroing (inclusive). May not be word aligned.
   569      * @param startOffset offset to begin zeroing. May not be word aligned.
   627      * @param endOffset offset to stop zeroing (exclusive). May not be word aligned.
       
   628      * @param isEndOffsetConstant is {@code endOffset} known to be constant in the snippet
   570      * @param manualUnroll maximally unroll zeroing
   629      * @param manualUnroll maximally unroll zeroing
   571      * @param useBulkZeroing apply bulk zeroing
   630      * @param supportsBulkZeroing whether bulk zeroing is supported by the backend
   572      */
   631      */
   573     private static void zeroMemory(long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll,
   632     private static void zeroMemory(Word memory, int startOffset, long endOffset, boolean isEndOffsetConstant, boolean manualUnroll,
   574                     boolean useBulkZeroing, Counters counters) {
   633                     boolean supportsBulkZeroing, Counters counters) {
   575         fillMemory(0, size, memory, constantSize, startOffset, manualUnroll, useBulkZeroing, counters);
   634         fillMemory(0, memory, startOffset, endOffset, isEndOffsetConstant, manualUnroll, supportsBulkZeroing, counters);
   576     }
   635     }
   577 
   636 
   578     private static void fillMemory(long value, long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll,
   637     private static void fillMemory(long value, Word memory, int startOffset, long endOffset, boolean constantOffsetLimit, boolean manualUnroll,
   579                     boolean useBulkZeroing, Counters counters) {
   638                     boolean supportsBulkZeroing, Counters counters) {
   580         ReplacementsUtil.runtimeAssert((size & 0x7) == 0, "unaligned object size");
   639         ReplacementsUtil.runtimeAssert((endOffset & 0x7) == 0, "unaligned object size");
   581         int offset = startOffset;
   640         int offset = startOffset;
   582         if ((offset & 0x7) != 0) {
   641         if ((offset & 0x7) != 0) {
   583             memory.writeInt(offset, (int) value, LocationIdentity.init());
   642             memory.writeInt(offset, (int) value, LocationIdentity.init());
   584             offset += 4;
   643             offset += 4;
   585         }
   644         }
   586         ReplacementsUtil.runtimeAssert((offset & 0x7) == 0, "unaligned offset");
   645         ReplacementsUtil.runtimeAssert((offset & 0x7) == 0, "unaligned offset");
   587         Counters theCounters = counters;
   646         Counters theCounters = counters;
   588         if (manualUnroll && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
   647         if (manualUnroll && ((endOffset - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
   589             ReplacementsUtil.staticAssert(!constantSize, "size shouldn't be constant at instantiation time");
   648             ReplacementsUtil.staticAssert(!constantOffsetLimit, "size shouldn't be constant at instantiation time");
   590             // This case handles arrays of constant length. Instead of having a snippet variant for
   649             // This case handles arrays of constant length. Instead of having a snippet variant for
   591             // each length, generate a chain of stores of maximum length. Once it's inlined the
   650             // each length, generate a chain of stores of maximum length. Once it's inlined the
   592             // break statement will trim excess stores.
   651             // break statement will trim excess stores.
   593             if (theCounters != null && theCounters.instanceSeqInit != null) {
   652             if (theCounters != null && theCounters.instanceSeqInit != null) {
   594                 theCounters.instanceSeqInit.inc();
   653                 theCounters.instanceSeqInit.inc();
   595             }
   654             }
   596 
   655 
   597             explodeLoop();
   656             explodeLoop();
   598             for (int i = 0; i < MAX_UNROLLED_OBJECT_ZEROING_STORES; i++, offset += 8) {
   657             for (int i = 0; i < MAX_UNROLLED_OBJECT_ZEROING_STORES; i++, offset += 8) {
   599                 if (offset == size) {
   658                 if (offset == endOffset) {
   600                     break;
   659                     break;
   601                 }
   660                 }
   602                 memory.initializeLong(offset, value, LocationIdentity.init());
   661                 memory.initializeLong(offset, value, LocationIdentity.init());
   603             }
   662             }
   604         } else {
   663         } else {
   605             // Use Word instead of int to avoid extension to long in generated code
   664             // Use Word instead of int to avoid extension to long in generated code
   606             Word off = WordFactory.signed(offset);
   665             Word off = WordFactory.signed(offset);
   607             if (useBulkZeroing && probability(SLOW_PATH_PROBABILITY, size >= getMinimalBulkZeroingSize(INJECTED_OPTIONVALUES))) {
   666             if (supportsBulkZeroing && value == 0 && probability(SLOW_PATH_PROBABILITY, (endOffset - offset) >= getMinimalBulkZeroingSize(INJECTED_OPTIONVALUES))) {
   608                 if (theCounters != null && theCounters.instanceBulkInit != null) {
   667                 if (theCounters != null && theCounters.instanceBulkInit != null) {
   609                     theCounters.instanceBulkInit.inc();
   668                     theCounters.instanceBulkInit.inc();
   610                 }
   669                 }
   611                 ZeroMemoryNode.zero(memory.add(off), size - offset, LocationIdentity.init());
   670                 ZeroMemoryNode.zero(memory.add(off), endOffset - offset, true, LocationIdentity.init());
   612             } else {
   671             } else {
   613                 if (constantSize && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
   672                 if (constantOffsetLimit && ((endOffset - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
   614                     if (theCounters != null && theCounters.instanceSeqInit != null) {
   673                     if (theCounters != null && theCounters.instanceSeqInit != null) {
   615                         theCounters.instanceSeqInit.inc();
   674                         theCounters.instanceSeqInit.inc();
   616                     }
   675                     }
   617                     explodeLoop();
   676                     explodeLoop();
   618                 } else {
   677                 } else {
   619                     if (theCounters != null && theCounters.instanceLoopInit != null) {
   678                     if (theCounters != null && theCounters.instanceLoopInit != null) {
   620                         theCounters.instanceLoopInit.inc();
   679                         theCounters.instanceLoopInit.inc();
   621                     }
   680                     }
   622                 }
   681                 }
   623                 for (; off.rawValue() < size; off = off.add(8)) {
   682                 for (; off.rawValue() < endOffset; off = off.add(8)) {
   624                     memory.initializeLong(off, value, LocationIdentity.init());
   683                     memory.initializeLong(off, value, LocationIdentity.init());
   625                 }
   684                 }
   626 
       
   627             }
   685             }
   628         }
   686         }
   629     }
   687     }
   630 
   688 
   631     @Fold
   689     @Fold
   635 
   693 
   636     /**
   694     /**
   637      * Fill uninitialized memory with garbage value in a newly allocated object, unrolling as
   695      * Fill uninitialized memory with garbage value in a newly allocated object, unrolling as
   638      * necessary and ensuring that stores are aligned.
   696      * necessary and ensuring that stores are aligned.
   639      *
   697      *
   640      * @param size number of bytes to zero
       
   641      * @param memory beginning of object which is being zeroed
   698      * @param memory beginning of object which is being zeroed
   642      * @param constantSize is {@code  size} known to be constant in the snippet
   699      * @param startOffset offset to begin filling garbage value (inclusive). May not be word
   643      * @param startOffset offset to begin zeroing. May not be word aligned.
   700      *            aligned.
       
   701      * @param endOffset offset to stop filling garbage value (exclusive). May not be word aligned.
       
   702      * @param isEndOffsetConstant is {@code  endOffset} known to be constant in the snippet
   644      * @param manualUnroll maximally unroll zeroing
   703      * @param manualUnroll maximally unroll zeroing
   645      */
   704      */
   646     private static void fillWithGarbage(long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) {
   705     private static void fillWithGarbage(Word memory, int startOffset, long endOffset, boolean isEndOffsetConstant, boolean manualUnroll, Counters counters) {
   647         fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, false, counters);
   706         fillMemory(0xfefefefefefefefeL, memory, startOffset, endOffset, isEndOffsetConstant, manualUnroll, false, counters);
   648     }
   707     }
   649 
   708 
   650     /**
   709     /**
   651      * Formats some allocated memory with an object header and zeroes out the rest.
   710      * Formats some allocated memory with an object header and zeroes out the rest.
   652      */
   711      */
   653     private static Object formatObject(KlassPointer hub, long size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, Counters counters) {
   712     private static Object formatObject(KlassPointer hub,
       
   713                     long size,
       
   714                     Word memory,
       
   715                     Word compileTimePrototypeMarkWord,
       
   716                     boolean fillContents,
       
   717                     boolean emitMemoryBarrier,
       
   718                     boolean constantSize,
       
   719                     Counters counters) {
   654         Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord;
   720         Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord;
   655         initializeObjectHeader(memory, prototypeMarkWord, hub);
   721         initializeObjectHeader(memory, prototypeMarkWord, hub);
   656         if (fillContents) {
   722         if (fillContents) {
   657             zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, false, counters);
   723             zeroMemory(memory, instanceHeaderSize(INJECTED_VMCONFIG), size, constantSize, false, false, counters);
   658         } else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
   724         } else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
   659             fillWithGarbage(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters);
   725             fillWithGarbage(memory, instanceHeaderSize(INJECTED_VMCONFIG), size, constantSize, false, counters);
   660         }
   726         }
   661         MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
   727         if (emitMemoryBarrier) {
       
   728             MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
       
   729         }
   662         return memory.toObjectNonNull();
   730         return memory.toObjectNonNull();
   663     }
   731     }
   664 
   732 
   665     @Snippet
   733     @Snippet
   666     private static void verifyHeap(@ConstantParameter Register threadRegister) {
   734     private static void verifyHeap(@ConstantParameter Register threadRegister) {
   672                 AssertionSnippets.vmMessageC(AssertionSnippets.ASSERTION_VM_MESSAGE_C, true, cstring("overzeroing of TLAB detected"), 0L, 0L, 0L);
   740                 AssertionSnippets.vmMessageC(AssertionSnippets.ASSERTION_VM_MESSAGE_C, true, cstring("overzeroing of TLAB detected"), 0L, 0L, 0L);
   673             }
   741             }
   674         }
   742         }
   675     }
   743     }
   676 
   744 
       
   745     @Snippet
       
   746     private static void threadBeingInitializedCheck(@ConstantParameter Register threadRegister, KlassPointer klass) {
       
   747         int state = readInstanceKlassInitState(klass);
       
   748         if (state != instanceKlassStateBeingInitialized(INJECTED_VMCONFIG)) {
       
   749             // The klass is no longer being initialized so force recompilation
       
   750             DeoptimizeNode.deopt(InvalidateRecompile, RuntimeConstraint);
       
   751         } else if (registerAsWord(threadRegister) != readInstanceKlassInitThread(klass)) {
       
   752             // The klass is being initialized but this isn't the initializing thread so
       
   753             // so deopt and allow execution to resume in the interpreter where it should block.
       
   754             DeoptimizeNode.deopt(None, RuntimeConstraint);
       
   755         }
       
   756     }
       
   757 
   677     /**
   758     /**
   678      * Formats some allocated memory with an object header and zeroes out the rest.
   759      * Formats some allocated memory with an object header and zeroes out the rest.
   679      */
   760      */
   680     private static Object formatArray(KlassPointer hub, long allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll,
   761     private static Object formatArray(KlassPointer hub,
   681                     boolean useBulkZeroing, Counters counters) {
   762                     long allocationSize,
       
   763                     int length,
       
   764                     int headerSize,
       
   765                     Word memory,
       
   766                     Word prototypeMarkWord,
       
   767                     boolean fillContents,
       
   768                     boolean emitMemoryBarrier,
       
   769                     boolean maybeUnroll,
       
   770                     boolean supportsBulkZeroing,
       
   771                     Counters counters) {
   682         memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init());
   772         memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init());
   683         /*
   773         /*
   684          * store hub last as the concurrent garbage collectors assume length is valid if hub field
   774          * store hub last as the concurrent garbage collectors assume length is valid if hub field
   685          * is not null
   775          * is not null
   686          */
   776          */
   687         initializeObjectHeader(memory, prototypeMarkWord, hub);
   777         initializeObjectHeader(memory, prototypeMarkWord, hub);
   688         if (fillContents) {
   778         if (fillContents) {
   689             zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, useBulkZeroing, counters);
   779             zeroMemory(memory, headerSize, allocationSize, false, maybeUnroll, supportsBulkZeroing, counters);
   690         } else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
   780         } else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
   691             fillWithGarbage(allocationSize, memory, false, headerSize, maybeUnroll, counters);
   781             fillWithGarbage(memory, headerSize, allocationSize, false, maybeUnroll, counters);
   692         }
   782         }
   693         MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
   783         if (emitMemoryBarrier) {
       
   784             MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
       
   785         }
   694         return memory.toObjectNonNull();
   786         return memory.toObjectNonNull();
   695     }
   787     }
   696 
   788 
   697     static class Counters {
   789     static class Counters {
   698         Counters(SnippetCounter.Group.Factory factory) {
   790         Counters(SnippetCounter.Group.Factory factory) {
   712         final SnippetCounter stub;
   804         final SnippetCounter stub;
   713     }
   805     }
   714 
   806 
   715     public static class Templates extends AbstractTemplates {
   807     public static class Templates extends AbstractTemplates {
   716 
   808 
   717         private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
   809         private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION,
       
   810                         PROTOTYPE_MARK_WORD_LOCATION);
   718         private final SnippetInfo allocateInstancePIC = snippet(NewObjectSnippets.class, "allocateInstancePIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
   811         private final SnippetInfo allocateInstancePIC = snippet(NewObjectSnippets.class, "allocateInstancePIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
   719                         TLAB_END_LOCATION);
   812                         TLAB_END_LOCATION, PROTOTYPE_MARK_WORD_LOCATION);
   720         private final SnippetInfo allocateArray = snippet(NewObjectSnippets.class, "allocateArray", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
   813         private final SnippetInfo allocateArray = snippet(NewObjectSnippets.class, "allocateArray", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
   721         private final SnippetInfo allocateArrayPIC = snippet(NewObjectSnippets.class, "allocateArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
   814         private final SnippetInfo allocateArrayPIC = snippet(NewObjectSnippets.class, "allocateArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
   722         private final SnippetInfo allocatePrimitiveArrayPIC = snippet(NewObjectSnippets.class, "allocatePrimitiveArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
   815         private final SnippetInfo allocatePrimitiveArrayPIC = snippet(NewObjectSnippets.class, "allocatePrimitiveArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
   723                         TLAB_END_LOCATION);
   816                         TLAB_END_LOCATION);
   724         private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, "allocateArrayDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
   817         private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, "allocateArrayDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
   725                         TLAB_END_LOCATION);
   818                         TLAB_END_LOCATION);
   726         private final SnippetInfo allocateInstanceDynamic = snippet(NewObjectSnippets.class, "allocateInstanceDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
   819         private final SnippetInfo allocateInstanceDynamic = snippet(NewObjectSnippets.class, "allocateInstanceDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
   727                         TLAB_END_LOCATION);
   820                         TLAB_END_LOCATION, PROTOTYPE_MARK_WORD_LOCATION, CLASS_INIT_STATE_LOCATION);
   728         private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray", TLAB_TOP_LOCATION, TLAB_END_LOCATION);
   821         private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray", TLAB_TOP_LOCATION, TLAB_END_LOCATION);
   729         private final SnippetInfo newmultiarrayPIC = snippet(NewObjectSnippets.class, "newmultiarrayPIC", TLAB_TOP_LOCATION, TLAB_END_LOCATION);
   822         private final SnippetInfo newmultiarrayPIC = snippet(NewObjectSnippets.class, "newmultiarrayPIC", TLAB_TOP_LOCATION, TLAB_END_LOCATION);
   730         private final SnippetInfo verifyHeap = snippet(NewObjectSnippets.class, "verifyHeap");
   823         private final SnippetInfo verifyHeap = snippet(NewObjectSnippets.class, "verifyHeap");
       
   824         private final SnippetInfo threadBeingInitializedCheck = snippet(NewObjectSnippets.class, "threadBeingInitializedCheck");
   731         private final GraalHotSpotVMConfig config;
   825         private final GraalHotSpotVMConfig config;
   732         private final Counters counters;
   826         private final Counters counters;
   733 
   827 
   734         public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target,
   828         public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target,
   735                         GraalHotSpotVMConfig config) {
   829                         GraalHotSpotVMConfig config) {
   753             Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage());
   847             Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage());
   754             args.addConst("size", size);
   848             args.addConst("size", size);
   755             args.add("hub", hub);
   849             args.add("hub", hub);
   756             args.add("prototypeMarkWord", type.prototypeMarkWord());
   850             args.add("prototypeMarkWord", type.prototypeMarkWord());
   757             args.addConst("fillContents", newInstanceNode.fillContents());
   851             args.addConst("fillContents", newInstanceNode.fillContents());
       
   852             args.addConst("emitMemoryBarrier", newInstanceNode.emitMemoryBarrier());
   758             args.addConst("threadRegister", registers.getThreadRegister());
   853             args.addConst("threadRegister", registers.getThreadRegister());
   759             args.addConst("constantSize", true);
   854             args.addConst("constantSize", true);
   760             args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? type.toJavaName(false) : "");
   855             args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? type.toJavaName(false) : "");
   761             args.addConst("counters", counters);
   856             args.addConst("counters", counters);
   762 
   857 
   796             assert arrayType.prototypeMarkWord() == lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord() : "all array types are assumed to have the same prototypeMarkWord";
   891             assert arrayType.prototypeMarkWord() == lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord() : "all array types are assumed to have the same prototypeMarkWord";
   797             args.add("prototypeMarkWord", arrayType.prototypeMarkWord());
   892             args.add("prototypeMarkWord", arrayType.prototypeMarkWord());
   798             args.addConst("headerSize", headerSize);
   893             args.addConst("headerSize", headerSize);
   799             args.addConst("log2ElementSize", log2ElementSize);
   894             args.addConst("log2ElementSize", log2ElementSize);
   800             args.addConst("fillContents", newArrayNode.fillContents());
   895             args.addConst("fillContents", newArrayNode.fillContents());
       
   896             args.addConst("emitMemoryBarrier", newArrayNode.emitMemoryBarrier());
   801             args.addConst("threadRegister", registers.getThreadRegister());
   897             args.addConst("threadRegister", registers.getThreadRegister());
   802             args.addConst("maybeUnroll", length.isConstant());
   898             args.addConst("maybeUnroll", length.isConstant());
   803             args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : "");
   899             args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : "");
   804             args.addConst("useBulkZeroing", tool.getLowerer().supportBulkZeroing());
   900             args.addConst("supportsBulkZeroing", tool.getLowerer().supportsBulkZeroing());
   805             args.addConst("counters", counters);
   901             args.addConst("counters", counters);
   806             SnippetTemplate template = template(newArrayNode, args);
   902             SnippetTemplate template = template(newArrayNode, args);
   807             graph.getDebug().log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
   903             graph.getDebug().log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
   808             template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args);
   904             template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args);
   809         }
   905         }
   813             args.add("type", newInstanceNode.getInstanceType());
   909             args.add("type", newInstanceNode.getInstanceType());
   814             ValueNode classClass = newInstanceNode.getClassClass();
   910             ValueNode classClass = newInstanceNode.getClassClass();
   815             assert classClass != null;
   911             assert classClass != null;
   816             args.add("classClass", classClass);
   912             args.add("classClass", classClass);
   817             args.addConst("fillContents", newInstanceNode.fillContents());
   913             args.addConst("fillContents", newInstanceNode.fillContents());
       
   914             args.addConst("emitMemoryBarrier", newInstanceNode.emitMemoryBarrier());
   818             args.addConst("threadRegister", registers.getThreadRegister());
   915             args.addConst("threadRegister", registers.getThreadRegister());
   819             args.addConst("counters", counters);
   916             args.addConst("counters", counters);
   820 
   917 
   821             SnippetTemplate template = template(newInstanceNode, args);
   918             SnippetTemplate template = template(newInstanceNode, args);
   822             template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args);
   919             template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args);
   830             assert voidClass != null;
   927             assert voidClass != null;
   831             args.add("voidClass", voidClass);
   928             args.add("voidClass", voidClass);
   832             ValueNode length = newArrayNode.length();
   929             ValueNode length = newArrayNode.length();
   833             args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length));
   930             args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length));
   834             args.addConst("fillContents", newArrayNode.fillContents());
   931             args.addConst("fillContents", newArrayNode.fillContents());
       
   932             args.addConst("emitMemoryBarrier", newArrayNode.emitMemoryBarrier());
   835             args.addConst("threadRegister", registers.getThreadRegister());
   933             args.addConst("threadRegister", registers.getThreadRegister());
   836             /*
   934             /*
   837              * We use Kind.Illegal as a marker value instead of null because constant snippet
   935              * We use Kind.Illegal as a marker value instead of null because constant snippet
   838              * parameters cannot be null.
   936              * parameters cannot be null.
   839              */
   937              */
   841             if (newArrayNode.getKnownElementKind() != null) {
   939             if (newArrayNode.getKnownElementKind() != null) {
   842                 args.addConst("knownLayoutHelper", lookupArrayClass(tool, newArrayNode.getKnownElementKind()).layoutHelper());
   940                 args.addConst("knownLayoutHelper", lookupArrayClass(tool, newArrayNode.getKnownElementKind()).layoutHelper());
   843             } else {
   941             } else {
   844                 args.addConst("knownLayoutHelper", 0);
   942                 args.addConst("knownLayoutHelper", 0);
   845             }
   943             }
   846             args.addConst("useBulkZeroing", tool.getLowerer().supportBulkZeroing());
   944             args.addConst("supportsBulkZeroing", tool.getLowerer().supportsBulkZeroing());
   847             args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord());
   945             args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord());
   848             args.addConst("counters", counters);
   946             args.addConst("counters", counters);
   849             SnippetTemplate template = template(newArrayNode, args);
   947             SnippetTemplate template = template(newArrayNode, args);
   850             template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args);
   948             template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args);
   851         }
   949         }
   888                 template.instantiate(providers.getMetaAccess(), verifyHeapNode, DEFAULT_REPLACER, args);
   986                 template.instantiate(providers.getMetaAccess(), verifyHeapNode, DEFAULT_REPLACER, args);
   889             } else {
   987             } else {
   890                 GraphUtil.removeFixedWithUnusedInputs(verifyHeapNode);
   988                 GraphUtil.removeFixedWithUnusedInputs(verifyHeapNode);
   891             }
   989             }
   892         }
   990         }
       
   991 
       
   992         public void lower(KlassBeingInitializedCheckNode verifyHeapNode, HotSpotRegistersProvider registers, LoweringTool tool) {
       
   993             Arguments args = new Arguments(threadBeingInitializedCheck, verifyHeapNode.graph().getGuardsStage(), tool.getLoweringStage());
       
   994             args.addConst("threadRegister", registers.getThreadRegister());
       
   995             args.add("klass", verifyHeapNode.getKlass());
       
   996 
       
   997             SnippetTemplate template = template(verifyHeapNode, args);
       
   998             template.instantiate(providers.getMetaAccess(), verifyHeapNode, DEFAULT_REPLACER, args);
       
   999         }
   893     }
  1000     }
   894 }
  1001 }