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 |