Avoid unnecessary work for identical locations in Buffer.BlockCopy
authorBen Adams <thundercat@illyriad.co.uk>
Tue, 3 Feb 2015 21:41:36 +0000 (21:41 +0000)
committerben_a_adams <ben.adams@ageofascent.com>
Wed, 4 Feb 2015 19:47:15 +0000 (19:47 +0000)
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.

src/vm/comutilnative.cpp

index 8c27b2f..ae9a9c1 100644 (file)
@@ -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();