/** * Low level copy of len elements from src[srcPos] to dst[dstPos]. * * <p>Assumption src != dst || (srcPos >= dstPos + 2). * * @param src the source array * @param srcPos index in the source array to begin copy * @param dst the destination array * @param dstPos index in the destination array to being copy * @param len number of array elements to copy */ @Inline public static void arraycopy16Bit(Object src, int srcPos, Object dst, int dstPos, int len) { if (USE_NATIVE && len > (NATIVE_THRESHOLD >> LOG_BYTES_IN_SHORT)) { memcopy( VM_Magic.objectAsAddress(dst).plus(dstPos << LOG_BYTES_IN_SHORT), VM_Magic.objectAsAddress(src).plus(srcPos << LOG_BYTES_IN_SHORT), len << LOG_BYTES_IN_SHORT); } else { if (len >= (BYTES_IN_ADDRESS >>> LOG_BYTES_IN_SHORT) && (srcPos & ((BYTES_IN_ADDRESS - 1) >>> LOG_BYTES_IN_SHORT)) == (dstPos & ((BYTES_IN_ADDRESS - 1) >>> LOG_BYTES_IN_SHORT))) { // relative alignment is the same int byteStart = srcPos << LOG_BYTES_IN_SHORT; int wordStart = alignUp(byteStart, BYTES_IN_ADDRESS); int wordEnd = alignDown(byteStart + (len << LOG_BYTES_IN_SHORT), BYTES_IN_ADDRESS); int byteEnd = byteStart + (len << LOG_BYTES_IN_SHORT); int startDiff = wordStart - byteStart; int endDiff = byteEnd - wordEnd; int wordLen = wordEnd - wordStart; Address srcPtr = VM_Magic.objectAsAddress(src).plus((srcPos << LOG_BYTES_IN_SHORT) + startDiff); Address dstPtr = VM_Magic.objectAsAddress(dst).plus((dstPos << LOG_BYTES_IN_SHORT) + startDiff); if (VM.BuildFor64Addr) { switch (startDiff) { case 6: dstPtr.store( srcPtr.loadChar(Offset.fromIntSignExtend(-6)), Offset.fromIntSignExtend(-6)); case 4: dstPtr.store( srcPtr.loadChar(Offset.fromIntSignExtend(-4)), Offset.fromIntSignExtend(-4)); case 2: dstPtr.store( srcPtr.loadChar(Offset.fromIntSignExtend(-2)), Offset.fromIntSignExtend(-2)); } } else { if (startDiff == 2) { dstPtr.store( srcPtr.loadChar(Offset.fromIntSignExtend(-2)), Offset.fromIntSignExtend(-2)); } } Address endPtr = srcPtr.plus(wordLen); while (srcPtr.LT(endPtr)) { dstPtr.store(srcPtr.loadWord()); srcPtr = srcPtr.plus(BYTES_IN_ADDRESS); dstPtr = dstPtr.plus(BYTES_IN_ADDRESS); } if (VM.BuildFor64Addr) { switch (endDiff) { case 6: dstPtr.store( srcPtr.loadChar(Offset.fromIntSignExtend(4)), Offset.fromIntSignExtend(4)); case 4: dstPtr.store( srcPtr.loadChar(Offset.fromIntSignExtend(2)), Offset.fromIntSignExtend(2)); case 2: dstPtr.store(srcPtr.loadChar()); } } else { if (endDiff == 2) { dstPtr.store(srcPtr.loadChar()); } } } else { Address srcPtr = VM_Magic.objectAsAddress(src).plus(srcPos << LOG_BYTES_IN_CHAR); Address dstPtr = VM_Magic.objectAsAddress(dst).plus(dstPos << LOG_BYTES_IN_CHAR); Address endPtr = srcPtr.plus(len << LOG_BYTES_IN_CHAR); while (srcPtr.LT(endPtr)) { dstPtr.store(srcPtr.loadChar()); srcPtr = srcPtr.plus(2); dstPtr = dstPtr.plus(2); } } } }
@Inline private static void copy2Bytes(Address dstPtr, Address srcPtr) { dstPtr.store(srcPtr.loadChar()); }