diff --git a/src/CLR/CorLib/corlib_native.cpp b/src/CLR/CorLib/corlib_native.cpp index 116fa8e0a9..640b6d2149 100644 --- a/src/CLR/CorLib/corlib_native.cpp +++ b/src/CLR/CorLib/corlib_native.cpp @@ -702,6 +702,7 @@ static const CLR_RT_MethodHandler method_lookup[] = nullptr, nullptr, nullptr, + Library_corlib_native_System_ReadOnlySpan_1::CopyTo___VOID__SystemSpan_1, nullptr, nullptr, nullptr, @@ -1613,7 +1614,7 @@ const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib = #if (NANOCLR_REFLECTION == TRUE) - 0xF1828DE7, + 0x4619DD1E, #elif (NANOCLR_REFLECTION == FALSE) @@ -1624,7 +1625,7 @@ const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib = #endif method_lookup, - { 100, 22, 0, 0 } + { 100, 22, 0, 1 } }; // clang-format on diff --git a/src/CLR/CorLib/corlib_native.h b/src/CLR/CorLib/corlib_native.h index 733223ce5e..24feb42cd0 100644 --- a/src/CLR/CorLib/corlib_native.h +++ b/src/CLR/CorLib/corlib_native.h @@ -786,6 +786,7 @@ struct Library_corlib_native_System_ReadOnlySpan_1 static const int FIELD___length = 2; NANOCLR_NATIVE_DECLARE(_ctor___VOID__VOIDptr__I4); + NANOCLR_NATIVE_DECLARE(CopyTo___VOID__SystemSpan_1); NANOCLR_NATIVE_DECLARE(NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4); //--// diff --git a/src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp b/src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp index a87a3d6ebb..00b34c16b5 100644 --- a/src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp +++ b/src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp @@ -7,6 +7,7 @@ #include "CorLib.h" typedef Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers RuntimeHelpers; +typedef Library_corlib_native_System_Span_1 Span_1; HRESULT Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4(CLR_RT_StackFrame &stack) { @@ -105,6 +106,47 @@ HRESULT Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4(C NANOCLR_NOCLEANUP(); } +HRESULT Library_corlib_native_System_ReadOnlySpan_1::CopyTo___VOID__SystemSpan_1(CLR_RT_StackFrame &stack) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array *sourceArray; + CLR_RT_HeapBlock_Array *destinationArray; + CLR_RT_HeapBlock *thisSpan = stack.This(); + CLR_RT_HeapBlock *destinationSpan = stack.Arg1().Dereference(); + + // check lengths - destination must be at least as large as source + if (thisSpan[FIELD___length].NumericByRefConst().u4 > + destinationSpan[Span_1::FIELD___length].NumericByRefConst().u4) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // get pointers to the arrays + sourceArray = thisSpan[FIELD___array].DereferenceArray(); + destinationArray = destinationSpan[Span_1::FIELD___array].DereferenceArray(); + + { + // sanity check for empty source array + if (thisSpan[FIELD___length].NumericByRefConst().s4 == 0) + { + NANOCLR_SET_AND_LEAVE(S_OK); + } + + // prevent GC from moving the arrays while we copy the data + CLR_RT_ProtectFromGC gc1(*sourceArray); + CLR_RT_ProtectFromGC gc2(*destinationArray); + + // use memmove to safely handle potential overlapping memory regions + memmove( + destinationArray->GetElement(0), + sourceArray->GetElement(0), + thisSpan[FIELD___length].NumericByRefConst().s4 * sourceArray->m_sizeOfElement); + } + + NANOCLR_NOCLEANUP(); +} + HRESULT Library_corlib_native_System_ReadOnlySpan_1::NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4( CLR_RT_StackFrame &stack) {