diff options
author | Ben Adams <thundercat@illyriad.co.uk> | 2015-02-03 21:41:36 +0000 |
---|---|---|
committer | ben_a_adams <ben.adams@ageofascent.com> | 2015-02-04 19:47:15 +0000 |
commit | a5dd659fdc1719f943fead7e1b6e2db167a271a4 (patch) | |
tree | 21682a83d1b5b74faa97ce37d4a65c6c4a250bae | |
parent | b846bb46cfa695d7fc39993a70a4d0add762d6c3 (diff) | |
download | coreclr-a5dd659fdc1719f943fead7e1b6e2db167a271a4.tar.gz coreclr-a5dd659fdc1719f943fead7e1b6e2db167a271a4.tar.bz2 coreclr-a5dd659fdc1719f943fead7e1b6e2db167a271a4.zip |
Avoid unnecessary work for identical locations in Buffer.BlockCopy
Perform validity checks to ensure parameters are correct but short-circuit
out memmove when exactly the same data would be copied to the same location.
There are a number of occasions; which can be intentional or unintentional,
where the buffer being copied is the same place - e.g an internal buffer is
the same as the return buffer, and there is no need to call memmove's
overwrite safe copy.
Generally the call to BlockCopy will be in a library so it is more practical
to enable the check here rather than alter all the calling functions,
including 3rd party libraries to preform additional checks.
-rw-r--r-- | src/vm/comutilnative.cpp | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/src/vm/comutilnative.cpp b/src/vm/comutilnative.cpp index 8c27b2f478..ae9a9c18ed 100644 --- a/src/vm/comutilnative.cpp +++ b/src/vm/comutilnative.cpp @@ -1443,9 +1443,12 @@ FCIMPL5(VOID, Buffer::BlockCopy, ArrayBase *src, int srcOffset, ArrayBase *dst, if (srcLen < (SIZE_T)srcOffset + (SIZE_T)count || dstLen < (SIZE_T)dstOffset + (SIZE_T)count) { FCThrowArgumentVoid(NULL, W("Argument_InvalidOffLen")); } + + PTR_BYTE srcPtr = src->GetDataPtr() + srcOffset; + PTR_BYTE dstPtr = dst->GetDataPtr() + dstOffset; - if (count > 0) { - memmove(dst->GetDataPtr() + dstOffset, src->GetDataPtr() + srcOffset, count); + if ((srcPtr != dstPtr) && (count > 0)) { + memmove(dstPtr, srcPtr, count); } FC_GC_POLL(); |