Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit a46eae1

Browse files
committed
Add a fast path for byte[] to Buffer.BlockCopy
1 parent bf15d88 commit a46eae1

File tree

1 file changed

+38
-12
lines changed

1 file changed

+38
-12
lines changed

src/vm/comutilnative.cpp

+38-12
Original file line numberDiff line numberDiff line change
@@ -1402,6 +1402,7 @@ void QCALLTYPE ExceptionNative::GetMessageFromNativeResources(ExceptionMessageKi
14021402
END_QCALL;
14031403
}
14041404

1405+
static MethodTable * g_pByteArrayMT;
14051406

14061407
// BlockCopy
14071408
// This method from one primitive array to another based
@@ -1416,20 +1417,45 @@ FCIMPL5(VOID, Buffer::BlockCopy, ArrayBase *src, int srcOffset, ArrayBase *dst,
14161417
if (src==NULL || dst==NULL)
14171418
FCThrowArgumentNullVoid((src==NULL) ? W("src") : W("dst"));
14181419

1419-
// Size of the Arrays in bytes
1420-
SIZE_T srcLen = src->GetNumComponents() * src->GetComponentSize();
1421-
SIZE_T dstLen = srcLen;
1420+
SIZE_T srcLen, dstLen;
14221421

1423-
// We only want to allow arrays of primitives, no Objects.
1424-
const CorElementType srcET = src->GetArrayElementType();
1425-
if (!CorTypeInfo::IsPrimitiveType_NoThrow(srcET))
1426-
FCThrowArgumentVoid(W("src"), W("Arg_MustBePrimArray"));
1422+
//
1423+
// Use specialized fast path for byte arrays because of it is what Buffer::BlockCopy is
1424+
// typically used for.
1425+
//
14271426

1428-
if (src != dst) {
1429-
const CorElementType dstET = dst->GetArrayElementType();
1430-
if (!CorTypeInfo::IsPrimitiveType_NoThrow(dstET))
1431-
FCThrowArgumentVoid(W("dest"), W("Arg_MustBePrimArray"));
1432-
dstLen = dst->GetNumComponents() * dst->GetComponentSize();
1427+
MethodTable * pByteArrayMT = g_pByteArrayMT;
1428+
if (pByteArrayMT == NULL)
1429+
{
1430+
if (g_pPredefinedArrayTypes[ELEMENT_TYPE_U1] != NULL)
1431+
{
1432+
pByteArrayMT = g_pPredefinedArrayTypes[ELEMENT_TYPE_U1]->GetMethodTable();
1433+
g_pByteArrayMT = pByteArrayMT;
1434+
}
1435+
}
1436+
1437+
if (src->GetMethodTable() == pByteArrayMT && dst->GetMethodTable() == pByteArrayMT)
1438+
{
1439+
srcLen = src->GetNumComponents();
1440+
dstLen = dst->GetNumComponents();
1441+
}
1442+
else
1443+
{
1444+
// Size of the Arrays in bytes
1445+
srcLen = src->GetNumComponents() * src->GetComponentSize();
1446+
dstLen = srcLen;
1447+
1448+
// We only want to allow arrays of primitives, no Objects.
1449+
const CorElementType srcET = src->GetArrayElementType();
1450+
if (!CorTypeInfo::IsPrimitiveType_NoThrow(srcET))
1451+
FCThrowArgumentVoid(W("src"), W("Arg_MustBePrimArray"));
1452+
1453+
if (src != dst) {
1454+
const CorElementType dstET = dst->GetArrayElementType();
1455+
if (!CorTypeInfo::IsPrimitiveType_NoThrow(dstET))
1456+
FCThrowArgumentVoid(W("dest"), W("Arg_MustBePrimArray"));
1457+
dstLen = dst->GetNumComponents() * dst->GetComponentSize();
1458+
}
14331459
}
14341460

14351461
if (srcOffset < 0 || dstOffset < 0 || count < 0) {

0 commit comments

Comments
 (0)