252 @ConstantParameter Counters counters) {
253 // Klass must be initialized by the time the first instance is allocated, therefore we can
254 // just load it from the corresponding cell and avoid the resolution check. We have to use a
255 // fixed load though, to prevent it from floating above the initialization.
256 KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
257 return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters));
258 }
259
260 @Snippet
261 public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
262 @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
263 if (probability(SLOW_PATH_PROBABILITY, type == null)) {
264 DeoptimizeNode.deopt(None, RuntimeConstraint);
265 }
266 Class<?> nonNullType = PiNode.piCastNonNullClass(type, SnippetAnchorNode.anchor());
267
268 if (probability(SLOW_PATH_PROBABILITY, DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) {
269 DeoptimizeNode.deopt(None, RuntimeConstraint);
270 }
271
272 return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(fillContents, threadRegister, options, counters, nonNullType));
273 }
274
275 private static Object allocateInstanceDynamicHelper(boolean fillContents, Register threadRegister, OptionValues options, Counters counters, Class<?> nonNullType) {
276 KlassPointer hub = ClassGetHubNode.readClass(nonNullType);
277 if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) {
278 KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor());
279
280 if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(nonNullHub))) {
281 int layoutHelper = readLayoutHelper(nonNullHub);
282 /*
283 * src/share/vm/oops/klass.hpp: For instances, layout helper is a positive number,
284 * the instance size. This size is already passed through align_object_size and
285 * scaled to bytes. The low order bit is set if instances of this class cannot be
286 * allocated using the fastpath.
287 */
288 if (probability(FAST_PATH_PROBABILITY, (layoutHelper & 1) == 0)) {
289 Word prototypeMarkWord = nonNullHub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION);
290 /*
291 * FIXME(je,ds): we should actually pass typeContext instead of "" but late
292 * binding of parameters is not yet supported by the GraphBuilderPlugin system.
293 */
294 return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", options, counters);
295 }
296 } else {
297 DeoptimizeNode.deopt(None, RuntimeConstraint);
298 }
299 }
300 DeoptimizeNode.deopt(None, RuntimeConstraint);
301 return null;
302 }
303
304 /**
305 * Maximum array length for which fast path allocation is used.
306 */
307 public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF;
308
309 @Snippet
310 public static Object allocatePrimitiveArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
311 @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext,
312 @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
313 // Primitive array types are eagerly pre-resolved. We can use a floating load.
314 KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub);
315 return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
316 }
317
318 @Snippet
319 public static Object allocateArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
320 @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext,
321 @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
368 } else {
369 result = newArrayStub(hub, length);
370 }
371 profileAllocation("array", allocationSize, typeContext, options);
372 return result;
373 }
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
383 @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
384 private static native Object newArray(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length);
385
386 @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = false)
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 }
398
399 @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
400 public static native Object dynamicNewInstance(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
401
402 @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = false)
403 public static native Object dynamicNewInstanceOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
404
405 @Snippet
406 public static Object allocateArrayDynamic(Class<?> elementType, Class<?> voidClass, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
407 @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord, @ConstantParameter OptionValues options,
|
252 @ConstantParameter Counters counters) {
253 // Klass must be initialized by the time the first instance is allocated, therefore we can
254 // just load it from the corresponding cell and avoid the resolution check. We have to use a
255 // fixed load though, to prevent it from floating above the initialization.
256 KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
257 return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters));
258 }
259
260 @Snippet
261 public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
262 @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
263 if (probability(SLOW_PATH_PROBABILITY, type == null)) {
264 DeoptimizeNode.deopt(None, RuntimeConstraint);
265 }
266 Class<?> nonNullType = PiNode.piCastNonNullClass(type, SnippetAnchorNode.anchor());
267
268 if (probability(SLOW_PATH_PROBABILITY, DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) {
269 DeoptimizeNode.deopt(None, RuntimeConstraint);
270 }
271
272 return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, options, counters, nonNullType));
273 }
274
275 private static Object allocateInstanceDynamicHelper(Class<?> type, boolean fillContents, Register threadRegister, OptionValues options, Counters counters, Class<?> nonNullType) {
276 KlassPointer hub = ClassGetHubNode.readClass(nonNullType);
277 if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) {
278 KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor());
279
280 if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(nonNullHub))) {
281 int layoutHelper = readLayoutHelper(nonNullHub);
282 /*
283 * src/share/vm/oops/klass.hpp: For instances, layout helper is a positive number,
284 * the instance size. This size is already passed through align_object_size and
285 * scaled to bytes. The low order bit is set if instances of this class cannot be
286 * allocated using the fastpath.
287 */
288 if (probability(FAST_PATH_PROBABILITY, (layoutHelper & 1) == 0)) {
289 Word prototypeMarkWord = nonNullHub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION);
290 /*
291 * FIXME(je,ds): we should actually pass typeContext instead of "" but late
292 * binding of parameters is not yet supported by the GraphBuilderPlugin system.
293 */
294 return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", options, counters);
295 }
296 } else {
297 DeoptimizeNode.deopt(None, RuntimeConstraint);
298 }
299 }
300 return dynamicNewInstanceStub(type);
301 }
302
303 /**
304 * Maximum array length for which fast path allocation is used.
305 */
306 public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF;
307
308 @Snippet
309 public static Object allocatePrimitiveArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
310 @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext,
311 @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
312 // Primitive array types are eagerly pre-resolved. We can use a floating load.
313 KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub);
314 return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
315 }
316
317 @Snippet
318 public static Object allocateArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
319 @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext,
320 @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
367 } else {
368 result = newArrayStub(hub, length);
369 }
370 profileAllocation("array", allocationSize, typeContext, options);
371 return result;
372 }
373
374 public static Object newArrayStub(KlassPointer hub, int length) {
375 if (useNullAllocationStubs(INJECTED_VMCONFIG)) {
376 return nonNullOrDeopt(newArrayOrNull(NEW_ARRAY_OR_NULL, hub, length));
377 } else {
378 return newArray(NEW_ARRAY, hub, length);
379 }
380 }
381
382 @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
383 private static native Object newArray(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length);
384
385 @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = false)
386 private static native Object newArrayOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length);
387
388 /**
389 * New dynamic array stub that throws an {@link OutOfMemoryError} on allocation failure.
390 */
391 public static final ForeignCallDescriptor DYNAMIC_NEW_INSTANCE = new ForeignCallDescriptor("dynamic_new_instance", Object.class, Class.class);
392
393 /**
394 * New dynamic array stub that returns null on allocation failure.
395 */
396 public static final ForeignCallDescriptor DYNAMIC_NEW_INSTANCE_OR_NULL = new ForeignCallDescriptor("dynamic_new_instance_or_null", Object.class, Class.class);
397
398 public static Object dynamicNewInstanceStub(Class<?> elementType) {
399 if (useNullAllocationStubs(INJECTED_VMCONFIG)) {
400 return nonNullOrDeopt(dynamicNewInstanceOrNull(DYNAMIC_NEW_INSTANCE_OR_NULL, elementType));
401 } else {
402 return dynamicNewInstance(DYNAMIC_NEW_INSTANCE, elementType);
403 }
404 }
405
406 /**
407 * Deoptimizes if {@code obj == null} otherwise returns {@code obj}.
408 */
409 private static Object nonNullOrDeopt(Object obj) {
410 if (obj == null) {
411 DeoptimizeNode.deopt(None, RuntimeConstraint);
412 }
413 return obj;
414 }
415
416 @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
417 public static native Object dynamicNewInstance(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
418
419 @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = false)
420 public static native Object dynamicNewInstanceOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
421
422 @Snippet
423 public static Object allocateArrayDynamic(Class<?> elementType, Class<?> voidClass, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
424 @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord, @ConstantParameter OptionValues options,
|