Skip to content

Commit 19de63c

Browse files
authored
Add CopyTo() to ReadOnlySpan<T> (#3251)
***NO_CI***
1 parent 1ae4494 commit 19de63c

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

src/CLR/CorLib/corlib_native.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
702702
nullptr,
703703
nullptr,
704704
nullptr,
705+
Library_corlib_native_System_ReadOnlySpan_1::CopyTo___VOID__SystemSpan_1,
705706
nullptr,
706707
nullptr,
707708
nullptr,
@@ -1613,7 +1614,7 @@ const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib =
16131614

16141615
#if (NANOCLR_REFLECTION == TRUE)
16151616

1616-
0xF1828DE7,
1617+
0x4619DD1E,
16171618

16181619
#elif (NANOCLR_REFLECTION == FALSE)
16191620

@@ -1624,7 +1625,7 @@ const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib =
16241625
#endif
16251626

16261627
method_lookup,
1627-
{ 100, 22, 0, 0 }
1628+
{ 100, 22, 0, 1 }
16281629
};
16291630

16301631
// clang-format on

src/CLR/CorLib/corlib_native.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,7 @@ struct Library_corlib_native_System_ReadOnlySpan_1
786786
static const int FIELD___length = 2;
787787

788788
NANOCLR_NATIVE_DECLARE(_ctor___VOID__VOIDptr__I4);
789+
NANOCLR_NATIVE_DECLARE(CopyTo___VOID__SystemSpan_1);
789790
NANOCLR_NATIVE_DECLARE(NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4);
790791

791792
//--//

src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "CorLib.h"
88

99
typedef Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers RuntimeHelpers;
10+
typedef Library_corlib_native_System_Span_1 Span_1;
1011

1112
HRESULT Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4(CLR_RT_StackFrame &stack)
1213
{
@@ -105,6 +106,47 @@ HRESULT Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4(C
105106
NANOCLR_NOCLEANUP();
106107
}
107108

109+
HRESULT Library_corlib_native_System_ReadOnlySpan_1::CopyTo___VOID__SystemSpan_1(CLR_RT_StackFrame &stack)
110+
{
111+
NANOCLR_HEADER();
112+
113+
CLR_RT_HeapBlock_Array *sourceArray;
114+
CLR_RT_HeapBlock_Array *destinationArray;
115+
CLR_RT_HeapBlock *thisSpan = stack.This();
116+
CLR_RT_HeapBlock *destinationSpan = stack.Arg1().Dereference();
117+
118+
// check lengths - destination must be at least as large as source
119+
if (thisSpan[FIELD___length].NumericByRefConst().u4 >
120+
destinationSpan[Span_1::FIELD___length].NumericByRefConst().u4)
121+
{
122+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
123+
}
124+
125+
// get pointers to the arrays
126+
sourceArray = thisSpan[FIELD___array].DereferenceArray();
127+
destinationArray = destinationSpan[Span_1::FIELD___array].DereferenceArray();
128+
129+
{
130+
// sanity check for empty source array
131+
if (thisSpan[FIELD___length].NumericByRefConst().s4 == 0)
132+
{
133+
NANOCLR_SET_AND_LEAVE(S_OK);
134+
}
135+
136+
// prevent GC from moving the arrays while we copy the data
137+
CLR_RT_ProtectFromGC gc1(*sourceArray);
138+
CLR_RT_ProtectFromGC gc2(*destinationArray);
139+
140+
// use memmove to safely handle potential overlapping memory regions
141+
memmove(
142+
destinationArray->GetElement(0),
143+
sourceArray->GetElement(0),
144+
thisSpan[FIELD___length].NumericByRefConst().s4 * sourceArray->m_sizeOfElement);
145+
}
146+
147+
NANOCLR_NOCLEANUP();
148+
}
149+
108150
HRESULT Library_corlib_native_System_ReadOnlySpan_1::NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4(
109151
CLR_RT_StackFrame &stack)
110152
{

0 commit comments

Comments
 (0)