The MSDN documentation for cpblk
is a bit sparse:
The
cpblk
instruction copies a number (typeunsigned int32
) of bytes from a source address (of type*
,native int
, or&
) to a destination address (of type*
,native int
, or&
). The behavior ofcpblk
is unspecified if the source and destination areas overlap.
cpblk
assumes that both the source and destination addressed are aligned to the natural size of the machine. Thecpblk
instruction can be immediately preceded by theunaligned.
instruction to indicate that either the source or the destination is unaligned.
Ok, compared to other bulk copy operations such as Array.Copy
, Marshal.Copy
, and Buffer.BlockCopy
, we know that:
- The size is measured in bytes
- The pointers should be aligned
This leaves me with some questions:
- Should the buffers be pinned first? Does it matter whether the operand type is
native int
, "unmanaged pointer" or "managed pointer (&
)"? - Are there restrictions on the type? (for example,
Buffer.BlockCopy
only works on primitive types, not structures even if they contain only primitive types)
According to https://stackoverflow.com/a/26380105/103167 pinning is unnecessary, but the supporting explanation is just wrong. (I suspect it is an overgeneralization from the fact that the Large Object Heap isn't compacted)
ECMA-335 isn't very helpful either. The instruction description there contains the same verbiage and adds
[Rationale:
cpblk
is intended for copying structures (rather than arbitrary byte-runs). All such structures, allocated by the CLI, are naturally aligned for the current platform. Therefore, there is no need for the compiler that generatescpblk
instructions to be aware of whether the code will eventually execute on a 32-bit or 64-bit platform. end rationale]
Ok, this sounds like it should accept more types than Buffer.BlockCopy
. But still not arbitrary types.
Perhaps the newly released .NET core source code will hold some answers.