@Snippet public static void arraycopyGeneric( Object src, int srcPos, Object dest, int destPos, int length) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); KlassPointer destHub = loadHub(nonNullDest); if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, nonNullSrc != nonNullDest)) { int layoutHelper = checkArrayType(srcHub); final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace(INJECTED_VMCONFIG)) == 0); checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); if (probability(FAST_PATH_PROBABILITY, isObjectArray)) { genericObjectExactCallCounter.inc(); genericObjectExactCallCopiedCounter.add(length); ArrayCopyCallNode.disjointArraycopy( nonNullSrc, srcPos, nonNullDest, destPos, length, JavaKind.Object); } else { genericPrimitiveCallCounter.inc(); genericPrimitiveCallCopiedCounter.add(length); UnsafeArrayCopyNode.arraycopyPrimitive( nonNullSrc, srcPos, nonNullDest, destPos, length, layoutHelper); } } else { SystemArraycopyCounter.inc(); SystemArraycopyCopiedCounter.add(length); System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length); } }
/** * This intrinsic is useful for the case where we know something statically about one of the * inputs but not the other. */ @Snippet public static void arraycopyPredictedExactIntrinsic( Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); KlassPointer destHub = loadHub(nonNullDest); if (probability(SLOW_PATH_PROBABILITY, srcHub != destHub)) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); counter.inc(); copiedCounter.add(length); ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind); if (length == 0) { zeroLengthDynamicCounter.inc(); } else { nonZeroLengthDynamicCounter.inc(); nonZeroLengthDynamicCopiedCounter.add(length); } }
@Snippet public static void arraycopyPredictedObjectWork( Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, KlassPointer objectArrayKlass, @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter) { if (length > 0) { KlassPointer srcHub = loadHub(PiNode.asNonNullObject(nonNullSrc)); KlassPointer destHub = loadHub(PiNode.asNonNullObject(nonNullDest)); if (probability(FAST_PATH_PROBABILITY, srcHub == destHub || destHub == objectArrayKlass)) { counter.inc(); copiedCounter.add(length); predictedObjectArrayCopyFastPathCounter.inc(); predictedObjectArrayCopyFastPathCopiedCounter.add(length); ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length); } else { predictedObjectArrayCopySlowPathCounter.inc(); predictedObjectArrayCopySlowPathCopiedCounter.add(length); System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length); } } }
@Snippet public static void checkcastArraycopyWork( Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length) { if (length > 0) { KlassPointer destKlass = loadHub(nonNullDest); KlassPointer srcKlass = loadHub(nonNullSrc); if (probability(SLOW_PATH_PROBABILITY, srcKlass == destKlass)) { // no storecheck required. objectCheckcastSameTypeCounter.inc(); objectCheckcastSameTypeCopiedCounter.add(length); ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length); } else { KlassPointer destElemKlass = destKlass.readKlassPointer( arrayClassElementOffset(INJECTED_VMCONFIG), OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION); Word superCheckOffset = Word.signed( destElemKlass.readInt( superCheckOffsetOffset(INJECTED_VMCONFIG), KLASS_SUPER_CHECK_OFFSET_LOCATION)); objectCheckcastCounter.inc(); objectCheckcastCopiedCounter.add(length); int copiedElements = CheckcastArrayCopyCallNode.checkcastArraycopy( nonNullSrc, srcPos, nonNullDest, destPos, length, superCheckOffset, destElemKlass, false); if (copiedElements != 0) { /* * the checkcast stub doesn't throw the ArrayStoreException, but returns the * number of copied elements (xor'd with -1). */ copiedElements ^= -1; System.arraycopy( nonNullSrc, srcPos + copiedElements, nonNullDest, destPos + copiedElements, length - copiedElements); } } } }
@Snippet public static void arraycopyExactIntrinsic( Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); counter.inc(); copiedCounter.add(length); ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind); if (length == 0) { zeroLengthDynamicCounter.inc(); } else { nonZeroLengthDynamicCounter.inc(); nonZeroLengthDynamicCopiedCounter.add(length); } }