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

Add a fast path for byte[] to Buffer.BlockCopy #3118

Merged
merged 1 commit into from
Feb 11, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/inc/dacvars.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions src/vm/appdomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
42 changes: 29 additions & 13 deletions src/vm/comutilnative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions src/vm/vars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/vm/vars.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down