diff --git a/src/inc/dacvars.h b/src/inc/dacvars.h index 310717ba431a..f4c7523cc015 100644 --- a/src/inc/dacvars.h +++ b/src/inc/dacvars.h @@ -235,6 +235,7 @@ DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pPredefinedArrayTypes, ::g_pPr DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_ArgumentHandleMT, ::g_ArgumentHandleMT) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_ArgIteratorMT, ::g_ArgIteratorMT) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_TypedReferenceMT, ::g_TypedReferenceMT) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pByteArrayMT, ::g_pByteArrayMT) #ifdef FEATURE_COMINTEROP DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pBaseCOMObject, ::g_pBaseCOMObject) diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index f695cc2cd629..9ab8c7dbc098 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -2918,6 +2918,10 @@ void SystemDomain::LoadBaseSystemClasses() _ASSERTE(g_pStringClass->GetBaseSize() == ObjSizeOf(StringObject)+sizeof(WCHAR)); _ASSERTE(g_pStringClass->GetComponentSize() == 2); + // Used by Buffer::BlockCopy + g_pByteArrayMT = ClassLoader::LoadArrayTypeThrowing( + TypeHandle(MscorlibBinder::GetElementType(ELEMENT_TYPE_U1))).AsArray()->GetMethodTable(); + #ifndef CROSSGEN_COMPILE ECall::PopulateManagedStringConstructors(); diff --git a/src/vm/comutilnative.cpp b/src/vm/comutilnative.cpp index d8a0a0c08ad7..d405bdae18fb 100644 --- a/src/vm/comutilnative.cpp +++ b/src/vm/comutilnative.cpp @@ -1402,7 +1402,6 @@ void QCALLTYPE ExceptionNative::GetMessageFromNativeResources(ExceptionMessageKi END_QCALL; } - // BlockCopy // This method from one primitive array to another based // upon an offset into each an a byte count. @@ -1416,20 +1415,37 @@ FCIMPL5(VOID, Buffer::BlockCopy, ArrayBase *src, int srcOffset, ArrayBase *dst, if (src==NULL || dst==NULL) FCThrowArgumentNullVoid((src==NULL) ? W("src") : W("dst")); - // Size of the Arrays in bytes - SIZE_T srcLen = src->GetNumComponents() * src->GetComponentSize(); - SIZE_T dstLen = srcLen; + SIZE_T srcLen, dstLen; - // We only want to allow arrays of primitives, no Objects. - const CorElementType srcET = src->GetArrayElementType(); - if (!CorTypeInfo::IsPrimitiveType_NoThrow(srcET)) - FCThrowArgumentVoid(W("src"), W("Arg_MustBePrimArray")); + // + // Use specialized fast path for byte arrays because of it is what Buffer::BlockCopy is + // typically used for. + // - if (src != dst) { - const CorElementType dstET = dst->GetArrayElementType(); - if (!CorTypeInfo::IsPrimitiveType_NoThrow(dstET)) - FCThrowArgumentVoid(W("dest"), W("Arg_MustBePrimArray")); - dstLen = dst->GetNumComponents() * dst->GetComponentSize(); + MethodTable * pByteArrayMT = g_pByteArrayMT; + _ASSERTE(pByteArrayMT != NULL); + if (src->GetMethodTable() == pByteArrayMT && dst->GetMethodTable() == pByteArrayMT) + { + srcLen = src->GetNumComponents(); + dstLen = dst->GetNumComponents(); + } + else + { + // Size of the Arrays in bytes + srcLen = src->GetNumComponents() * src->GetComponentSize(); + dstLen = srcLen; + + // We only want to allow arrays of primitives, no Objects. + const CorElementType srcET = src->GetArrayElementType(); + if (!CorTypeInfo::IsPrimitiveType_NoThrow(srcET)) + FCThrowArgumentVoid(W("src"), W("Arg_MustBePrimArray")); + + if (src != dst) { + const CorElementType dstET = dst->GetArrayElementType(); + if (!CorTypeInfo::IsPrimitiveType_NoThrow(dstET)) + FCThrowArgumentVoid(W("dest"), W("Arg_MustBePrimArray")); + dstLen = dst->GetNumComponents() * dst->GetComponentSize(); + } } if (srcOffset < 0 || dstOffset < 0 || count < 0) { diff --git a/src/vm/vars.cpp b/src/vm/vars.cpp index 4e5d29962def..a425a67853a7 100644 --- a/src/vm/vars.cpp +++ b/src/vm/vars.cpp @@ -88,6 +88,8 @@ GPTR_IMPL(MethodTable, g_ArgumentHandleMT); GPTR_IMPL(MethodTable, g_ArgIteratorMT); GPTR_IMPL(MethodTable, g_TypedReferenceMT); +GPTR_IMPL(MethodTable, g_pByteArrayMT); + #ifdef FEATURE_COMINTEROP GPTR_IMPL(MethodTable, g_pBaseCOMObject); GPTR_IMPL(MethodTable, g_pBaseRuntimeClass); diff --git a/src/vm/vars.hpp b/src/vm/vars.hpp index aa144889d1f2..faab0bcd7ffa 100644 --- a/src/vm/vars.hpp +++ b/src/vm/vars.hpp @@ -427,6 +427,8 @@ GPTR_DECL(MethodTable, g_ArgumentHandleMT); GPTR_DECL(MethodTable, g_ArgIteratorMT); GPTR_DECL(MethodTable, g_TypedReferenceMT); +GPTR_DECL(MethodTable, g_pByteArrayMT); + #ifdef FEATURE_COMINTEROP GPTR_DECL(MethodTable, g_pBaseCOMObject); GPTR_DECL(MethodTable, g_pBaseRuntimeClass);