// A very simple and efficient array copy that assumes all of the // parameter validation has already been done. All counts here are // in bytes. internal static unsafe void InternalBlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count) { VTable.Assert(src != null); VTable.Assert(dst != null); // Unfortunately, we must do a check to make sure we're writing // within the bounds of the array. This will ensure that we don't // overwrite memory elsewhere in the system nor do we write out junk. // This can happen if multiple threads screw with our IO classes // simultaneously without being threadsafe. Throw here. int srcLen = src.Length * src.vtable.arrayElementSize; if (srcOffset < 0 || dstOffset < 0 || count < 0 || srcOffset > srcLen - count) { throw new IndexOutOfRangeException ("IndexOutOfRange_IORaceCondition"); } if (src == dst) { if (dstOffset > srcLen - count) { throw new IndexOutOfRangeException ("IndexOutOfRange_IORaceCondition"); } } else { int dstLen = dst.Length * dst.vtable.arrayElementSize; if (dstOffset > dstLen - count) { throw new IndexOutOfRangeException ("IndexOutOfRange_IORaceCondition"); } } // Copy the data. // Call our faster version of memmove, not the CRT one. fixed(int *srcFieldPtr = &src.field1) { fixed(int *dstFieldPtr = &dst.field1) { byte *srcPtr = (byte *) src.GetFirstElementAddress(srcFieldPtr); byte *dstPtr = (byte *) dst.GetFirstElementAddress(dstFieldPtr); MoveMemory(dstPtr + dstOffset, srcPtr + srcOffset, count); } } }
private unsafe static void CloneVectorContents(Array srcArray, Array dstArray) { int srcLength = srcArray.Length; fixed(int *srcFieldPtr = &srcArray.field1) { fixed(int *dstFieldPtr = &dstArray.field1) { byte *srcDataPtr = (byte *) srcArray.GetFirstElementAddress(srcFieldPtr); byte *dstDataPtr = (byte *) dstArray.GetFirstElementAddress(dstFieldPtr); int size = srcArray.vtable.arrayElementSize * srcLength; Buffer.MoveMemory(dstDataPtr, srcDataPtr, size); } } }
private unsafe static void CloneArrayContents(Array srcArray, Array dstArray) { int srcLength = srcArray.Length; fixed(int *srcFieldPtr = &srcArray.field1) { fixed(int *dstFieldPtr = &dstArray.field1) { byte *srcDataPtr = (byte *) srcArray.GetFirstElementAddress(srcFieldPtr); byte *dstDataPtr = (byte *) dstArray.GetFirstElementAddress(dstFieldPtr); byte *srcDimPtr = (byte *) srcArray.GetFirstDimInfoRectangleArray(); int dimInfoSize = (int)(srcDataPtr - srcDimPtr); int size = srcArray.vtable.arrayElementSize * srcLength; Buffer.MoveMemory(dstDataPtr - dimInfoSize, srcDataPtr - dimInfoSize, size + dimInfoSize); } } }
public static unsafe void InitArray(System.Array srcArray, System.Array dstArray) { #if !REFERENCE_COUNTING_GC && !DEFERRED_REFERENCE_COUNTING_GC Barrier.ArrayCopy(srcArray, 0, dstArray, 0, srcArray.Length); #else fixed(int *srcFieldPtr = &srcArray.field1) { void *src = srcArray.GetFirstElementAddress(srcFieldPtr); fixed(int *dstFieldPtr = &dstArray.field1) { void *dst = dstArray.GetFirstElementAddress(dstFieldPtr); int size = (srcArray.vtable.arrayElementSize * srcArray.Length); #if REFERENCE_COUNTING_GC if (dstArray.vtable.arrayOf == StructuralType.Reference || dstArray.vtable.arrayOf == StructuralType.Struct) { int dstLength = size / dstArray.vtable.arrayElementSize; GCs.ReferenceCountingCollector. IncrementReferentRefCounts(Magic.addressOf(srcArray), srcArray.vtable, 0, srcArray.Length); GCs.ReferenceCountingCollector. DecrementReferentRefCounts(Magic.addressOf(dstArray), dstArray.vtable, 0, dstLength); } #elif DEFERRED_REFERENCE_COUNTING_GC if (dstArray.vtable.arrayOf == StructuralType.Reference || dstArray.vtable.arrayOf == StructuralType.Struct) { int dstLength = size / dstArray.vtable.arrayElementSize; GCs.DeferredReferenceCountingCollector. IncrementReferentRefCounts(Magic.addressOf(srcArray), srcArray.vtable, 0, srcArray.Length); GCs.DeferredReferenceCountingCollector. DecrementReferentRefCounts(Magic.addressOf(dstArray), dstArray.vtable, 0, dstLength); } #endif // REFERENCE_COUNTING_GC System.IO.__UnmanagedMemoryStream.memcpyimpl ((byte *)src, (byte *)dst, size); } } #endif // REFERENCE_COUNTING_GC }