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)
_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();
END_QCALL;
}
-
// BlockCopy
// This method from one primitive array to another based
// upon an offset into each an a byte count.
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) {
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);
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);