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

Commit

Permalink
Add a fast path for byte[] to Buffer.BlockCopy
Browse files Browse the repository at this point in the history
  • Loading branch information
jkotas committed Feb 11, 2016
1 parent bf15d88 commit 9583ed7
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 13 deletions.
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

0 comments on commit 9583ed7

Please sign in to comment.