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

Commit 9583ed7

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

File tree

5 files changed

+38
-13
lines changed

5 files changed

+38
-13
lines changed

src/inc/dacvars.h

+1
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pPredefinedArrayTypes, ::g_pPr
235235
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_ArgumentHandleMT, ::g_ArgumentHandleMT)
236236
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_ArgIteratorMT, ::g_ArgIteratorMT)
237237
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_TypedReferenceMT, ::g_TypedReferenceMT)
238+
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pByteArrayMT, ::g_pByteArrayMT)
238239

239240
#ifdef FEATURE_COMINTEROP
240241
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pBaseCOMObject, ::g_pBaseCOMObject)

src/vm/appdomain.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -2918,6 +2918,10 @@ void SystemDomain::LoadBaseSystemClasses()
29182918
_ASSERTE(g_pStringClass->GetBaseSize() == ObjSizeOf(StringObject)+sizeof(WCHAR));
29192919
_ASSERTE(g_pStringClass->GetComponentSize() == 2);
29202920

2921+
// Used by Buffer::BlockCopy
2922+
g_pByteArrayMT = ClassLoader::LoadArrayTypeThrowing(
2923+
TypeHandle(MscorlibBinder::GetElementType(ELEMENT_TYPE_U1))).AsArray()->GetMethodTable();
2924+
29212925
#ifndef CROSSGEN_COMPILE
29222926
ECall::PopulateManagedStringConstructors();
29232927

src/vm/comutilnative.cpp

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

1405-
14061405
// BlockCopy
14071406
// This method from one primitive array to another based
14081407
// upon an offset into each an a byte count.
@@ -1416,20 +1415,37 @@ FCIMPL5(VOID, Buffer::BlockCopy, ArrayBase *src, int srcOffset, ArrayBase *dst,
14161415
if (src==NULL || dst==NULL)
14171416
FCThrowArgumentNullVoid((src==NULL) ? W("src") : W("dst"));
14181417

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

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"));
1420+
//
1421+
// Use specialized fast path for byte arrays because of it is what Buffer::BlockCopy is
1422+
// typically used for.
1423+
//
14271424

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();
1425+
MethodTable * pByteArrayMT = g_pByteArrayMT;
1426+
_ASSERTE(pByteArrayMT != NULL);
1427+
if (src->GetMethodTable() == pByteArrayMT && dst->GetMethodTable() == pByteArrayMT)
1428+
{
1429+
srcLen = src->GetNumComponents();
1430+
dstLen = dst->GetNumComponents();
1431+
}
1432+
else
1433+
{
1434+
// Size of the Arrays in bytes
1435+
srcLen = src->GetNumComponents() * src->GetComponentSize();
1436+
dstLen = srcLen;
1437+
1438+
// We only want to allow arrays of primitives, no Objects.
1439+
const CorElementType srcET = src->GetArrayElementType();
1440+
if (!CorTypeInfo::IsPrimitiveType_NoThrow(srcET))
1441+
FCThrowArgumentVoid(W("src"), W("Arg_MustBePrimArray"));
1442+
1443+
if (src != dst) {
1444+
const CorElementType dstET = dst->GetArrayElementType();
1445+
if (!CorTypeInfo::IsPrimitiveType_NoThrow(dstET))
1446+
FCThrowArgumentVoid(W("dest"), W("Arg_MustBePrimArray"));
1447+
dstLen = dst->GetNumComponents() * dst->GetComponentSize();
1448+
}
14331449
}
14341450

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

src/vm/vars.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ GPTR_IMPL(MethodTable, g_ArgumentHandleMT);
8888
GPTR_IMPL(MethodTable, g_ArgIteratorMT);
8989
GPTR_IMPL(MethodTable, g_TypedReferenceMT);
9090

91+
GPTR_IMPL(MethodTable, g_pByteArrayMT);
92+
9193
#ifdef FEATURE_COMINTEROP
9294
GPTR_IMPL(MethodTable, g_pBaseCOMObject);
9395
GPTR_IMPL(MethodTable, g_pBaseRuntimeClass);

src/vm/vars.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ GPTR_DECL(MethodTable, g_ArgumentHandleMT);
427427
GPTR_DECL(MethodTable, g_ArgIteratorMT);
428428
GPTR_DECL(MethodTable, g_TypedReferenceMT);
429429

430+
GPTR_DECL(MethodTable, g_pByteArrayMT);
431+
430432
#ifdef FEATURE_COMINTEROP
431433
GPTR_DECL(MethodTable, g_pBaseCOMObject);
432434
GPTR_DECL(MethodTable, g_pBaseRuntimeClass);

0 commit comments

Comments
 (0)