/** * Low level copy of <code>len</code> elements from <code>src[srcPos]</code> to <code>dst[dstPos] * </code>. * * <p>Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 8 bytes. * * @param src the source array * @param srcIdx index in the source array to begin copy * @param dst the destination array * @param dstIdx index in the destination array to being copy * @param len number of array elements to copy */ @Inline public static void arraycopy64Bit(Object src, int srcIdx, Object dst, int dstIdx, int len) { Address srcPtr = VM_Magic.objectAsAddress(src).plus(srcIdx << LOG_BYTES_IN_DOUBLE); Address dstPtr = VM_Magic.objectAsAddress(dst).plus(dstIdx << LOG_BYTES_IN_DOUBLE); int copyBytes = len << LOG_BYTES_IN_DOUBLE; if (USE_NATIVE && len > (NATIVE_THRESHOLD >> LOG_BYTES_IN_DOUBLE)) { memcopy(dstPtr, srcPtr, copyBytes); } else { // The elements of long[] and double[] are always doubleword aligned // therefore we can do 64 bit load/stores without worrying about alignment. Address endPtr = srcPtr.plus(copyBytes); while (srcPtr.LT(endPtr)) { // We generate abysmal code on IA32 if we try to use the FP registers, // so use the gprs instead even though it results in more instructions. if (VM.BuildForIA32) { dstPtr.store(srcPtr.loadInt()); dstPtr.store(srcPtr.loadInt(Offset.fromIntSignExtend(4)), Offset.fromIntSignExtend(4)); } else { dstPtr.store(srcPtr.loadDouble()); } srcPtr = srcPtr.plus(8); dstPtr = dstPtr.plus(8); } } }
@Inline private static void copy8Bytes(Address dstPtr, Address srcPtr) { if (BYTES_IN_COPY == 8) { if (VM.BuildForIA32) { dstPtr.store(srcPtr.loadLong()); } else { dstPtr.store(srcPtr.loadDouble()); } } else { copy4Bytes(dstPtr, srcPtr); copy4Bytes(dstPtr.plus(4), srcPtr.plus(4)); } }