From da60602886a9cd4d5d15ca30638bac5d435d515d Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 30 Oct 2016 01:50:27 -0700 Subject: [PATCH] Streamline implementation of ToArray to call CopyTo directly Fix missing pinning in CopyTo Move and rename some JitHelpers to S.R.CS.Unsafe to make different implementations more similar Commit migrated from https://github.com/dotnet/coreclr/commit/c718ac41faceec2a69ddcc4eadd3ff1d45eb9141 --- .../src/mscorlib/mscorlib.shared.sources.props | 1 + .../src/mscorlib/src/System/ReadOnlySpan.cs | 27 ++-- .../src/System/Runtime/CompilerServices/Unsafe.cs | 68 ++++++++++ .../System/Runtime/CompilerServices/jithelpers.cs | 22 ---- src/coreclr/src/mscorlib/src/System/Span.cs | 63 +++++---- src/coreclr/src/vm/jitinterface.cpp | 141 +++++++++++++-------- src/coreclr/src/vm/mscorlib.h | 11 +- 7 files changed, 210 insertions(+), 123 deletions(-) create mode 100644 src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs diff --git a/src/coreclr/src/mscorlib/mscorlib.shared.sources.props b/src/coreclr/src/mscorlib/mscorlib.shared.sources.props index 2f7a616..d86a2dc 100644 --- a/src/coreclr/src/mscorlib/mscorlib.shared.sources.props +++ b/src/coreclr/src/mscorlib/mscorlib.shared.sources.props @@ -24,6 +24,7 @@ + diff --git a/src/coreclr/src/mscorlib/src/System/ReadOnlySpan.cs b/src/coreclr/src/mscorlib/src/System/ReadOnlySpan.cs index bf4216d..853c68f 100644 --- a/src/coreclr/src/mscorlib/src/System/ReadOnlySpan.cs +++ b/src/coreclr/src/mscorlib/src/System/ReadOnlySpan.cs @@ -55,7 +55,7 @@ namespace System if ((uint)start >= (uint)array.Length || (uint)length > (uint)(array.Length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(); - JitHelpers.SetByRef(out _rawPointer, ref JitHelpers.AddByRef(ref JitHelpers.GetArrayData(array), start)); + JitHelpers.SetByRef(out _rawPointer, ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start)); _length = length; } @@ -96,7 +96,7 @@ namespace System public static implicit operator ReadOnlySpan(Span slice) { - return new ReadOnlySpan(ref JitHelpers.GetByRef(ref slice._rawPointer), slice.Length); + return new ReadOnlySpan(ref JitHelpers.GetByRef(ref slice._rawPointer), slice._length); } public static implicit operator ReadOnlySpan(T[] array) @@ -137,7 +137,7 @@ namespace System if ((uint)index >= (uint)_length) ThrowHelper.ThrowIndexOutOfRangeException(); - return JitHelpers.AddByRef(ref JitHelpers.GetByRef(ref _rawPointer), index); + return Unsafe.Add(ref JitHelpers.GetByRef(ref _rawPointer), index); } } @@ -148,8 +148,11 @@ namespace System /// public T[] ToArray() { + if (_length == 0) + return Array.Empty(); + var destination = new T[_length]; - TryCopyTo(destination); + SpanHelper.CopyTo(ref JitHelpers.GetArrayData(destination), ref JitHelpers.GetByRef(ref _rawPointer), _length); return destination; } @@ -165,7 +168,7 @@ namespace System if ((uint)start > (uint)_length) ThrowHelper.ThrowArgumentOutOfRangeException(); - return new ReadOnlySpan(ref JitHelpers.AddByRef(ref JitHelpers.GetByRef(ref _rawPointer), start), Length - start); + return new ReadOnlySpan(ref Unsafe.Add(ref JitHelpers.GetByRef(ref _rawPointer), start), _length - start); } /// @@ -181,7 +184,7 @@ namespace System if ((uint)start >= (uint)_length || (uint)length > (uint)(_length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(); - return new ReadOnlySpan(ref JitHelpers.AddByRef(ref JitHelpers.GetByRef(ref _rawPointer), start), length); + return new ReadOnlySpan(ref Unsafe.Add(ref JitHelpers.GetByRef(ref _rawPointer), start), length); } /// @@ -191,7 +194,7 @@ namespace System public bool Equals(ReadOnlySpan other) { return (_length == other._length) && - (_length == 0 || JitHelpers.ByRefEquals(ref JitHelpers.GetByRef(ref _rawPointer), ref JitHelpers.GetByRef(ref other._rawPointer))); + (_length == 0 || Unsafe.AreSame(ref JitHelpers.GetByRef(ref _rawPointer), ref JitHelpers.GetByRef(ref other._rawPointer))); } /// @@ -201,10 +204,10 @@ namespace System /// The span to copy items into. public bool TryCopyTo(Span destination) { - if (Length > destination.Length) + if (_length > destination._length) return false; - SpanHelper.CopyTo(ref destination._rawPointer, ref _rawPointer, Length); + SpanHelper.CopyTo(ref JitHelpers.GetByRef(ref destination._rawPointer), ref JitHelpers.GetByRef(ref _rawPointer), _length); return true; } } @@ -242,7 +245,7 @@ namespace System if ((uint)start > (uint)text.Length) ThrowHelper.ThrowArgumentOutOfRangeException(); - return new ReadOnlySpan(ref JitHelpers.AddByRef(ref text.GetFirstCharRef(), start), text.Length - start); + return new ReadOnlySpan(ref Unsafe.Add(ref text.GetFirstCharRef(), start), text.Length - start); } /// @@ -263,7 +266,7 @@ namespace System if ((uint)start >= (uint)text.Length || (uint)length > (uint)(text.Length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(); - return new ReadOnlySpan(ref JitHelpers.AddByRef(ref text.GetFirstCharRef(), start), length); + return new ReadOnlySpan(ref Unsafe.Add(ref text.GetFirstCharRef(), start), length); } } -} \ No newline at end of file +} diff --git a/src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs b/src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs new file mode 100644 index 0000000..3ebc321 --- /dev/null +++ b/src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.Versioning; + +namespace System.Runtime.CompilerServices +{ + // + // Subsetted clone of System.Runtime.CompilerServices.Unsafe for internal runtime use. + // Keep in sync with https://github.com/dotnet/corefx/tree/master/src/System.Runtime.CompilerServices.Unsafe. + // + + /// + /// Contains generic, low-level functionality for manipulating pointers. + /// + internal static class Unsafe + { + /// + /// Returns the size of an object of the given type parameter. + /// + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SizeOf() + { + // The body of this function will be replaced by the EE with unsafe code that just returns sizeof !!T + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + /// + /// Reinterprets the given reference as a reference to a value of type . + /// + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref TTo As(ref TFrom source) + { + // The body of this function will be replaced by the EE with unsafe code that just returns sizeof !!T + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + /// + /// Adds an element offset to the given reference. + /// + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref T Add(ref T source, int elementOffset) + { + // The body of this function will be replaced by the EE with unsafe code!!! + // See getILIntrinsicImplementation for how this happens. + typeof(T).ToString(); // Type used by the actual method body + throw new InvalidOperationException(); + } + + /// + /// Determines whether the specified references point to the same location. + /// + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AreSame(ref T left, ref T right) + { + // The body of this function will be replaced by the EE with unsafe code!!! + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + } +} diff --git a/src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs b/src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs index 9cafc68..1ad7899 100644 --- a/src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs +++ b/src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs @@ -242,21 +242,6 @@ namespace System.Runtime.CompilerServices { throw new InvalidOperationException(); } - static internal ref T AddByRef(ref T pointer, int count) - { - // The body of this function will be replaced by the EE with unsafe code!!! - // See getILIntrinsicImplementation for how this happens. - typeof(T).ToString(); // Type used by the actual method body - throw new InvalidOperationException(); - } - - static internal bool ByRefEquals(ref T refA, ref T refB) - { - // The body of this function will be replaced by the EE with unsafe code!!! - // See getILIntrinsicImplementation for how this happens. - throw new InvalidOperationException(); - } - static internal bool ByRefLessThan(ref T refA, ref T refB) { // The body of this function will be replaced by the EE with unsafe code!!! @@ -264,13 +249,6 @@ namespace System.Runtime.CompilerServices { throw new InvalidOperationException(); } - static internal int SizeOf() - { - // The body of this function will be replaced by the EE with unsafe code that just returns sizeof !!T - // See getILIntrinsicImplementation for how this happens. - throw new InvalidOperationException(); - } - /// true if given type is reference type or value type that contains references static internal bool ContainsReferences() { diff --git a/src/coreclr/src/mscorlib/src/System/Span.cs b/src/coreclr/src/mscorlib/src/System/Span.cs index ee1c97e..2ef49fc 100644 --- a/src/coreclr/src/mscorlib/src/System/Span.cs +++ b/src/coreclr/src/mscorlib/src/System/Span.cs @@ -65,7 +65,7 @@ namespace System if ((uint)start >= (uint)array.Length || (uint)length > (uint)(array.Length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(); - JitHelpers.SetByRef(out _rawPointer, ref JitHelpers.AddByRef(ref JitHelpers.GetArrayData(array), start)); + JitHelpers.SetByRef(out _rawPointer, ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start)); _length = length; } @@ -142,14 +142,14 @@ namespace System if ((uint)index >= (uint)_length) ThrowHelper.ThrowIndexOutOfRangeException(); - return JitHelpers.AddByRef(ref JitHelpers.GetByRef(ref _rawPointer), index); + return Unsafe.Add(ref JitHelpers.GetByRef(ref _rawPointer), index); } set { if ((uint)index >= (uint)_length) ThrowHelper.ThrowIndexOutOfRangeException(); - JitHelpers.AddByRef(ref JitHelpers.GetByRef(ref _rawPointer), index) = value; + Unsafe.Add(ref JitHelpers.GetByRef(ref _rawPointer), index) = value; } } @@ -160,8 +160,11 @@ namespace System /// public T[] ToArray() { + if (_length == 0) + return Array.Empty(); + var destination = new T[_length]; - TryCopyTo(destination); + SpanHelper.CopyTo(ref JitHelpers.GetArrayData(destination), ref JitHelpers.GetByRef(ref _rawPointer), _length); return destination; } @@ -177,7 +180,7 @@ namespace System if ((uint)start > (uint)_length) ThrowHelper.ThrowArgumentOutOfRangeException(); - return new Span(ref JitHelpers.AddByRef(ref JitHelpers.GetByRef(ref _rawPointer), start), Length - start); + return new Span(ref Unsafe.Add(ref JitHelpers.GetByRef(ref _rawPointer), start), _length - start); } /// @@ -193,7 +196,7 @@ namespace System if ((uint)start >= (uint)_length || (uint)length > (uint)(_length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(); - return new Span(ref JitHelpers.AddByRef(ref JitHelpers.GetByRef(ref _rawPointer), start), length); + return new Span(ref Unsafe.Add(ref JitHelpers.GetByRef(ref _rawPointer), start), length); } /// @@ -203,7 +206,7 @@ namespace System public bool Equals(Span other) { return (_length == other._length) && - (_length == 0 || JitHelpers.ByRefEquals(ref JitHelpers.GetByRef(ref _rawPointer), ref JitHelpers.GetByRef(ref other._rawPointer))); + (_length == 0 || Unsafe.AreSame(ref JitHelpers.GetByRef(ref _rawPointer), ref JitHelpers.GetByRef(ref other._rawPointer))); } /// @@ -216,7 +219,7 @@ namespace System if (Length > destination.Length) return false; - SpanHelper.CopyTo(ref destination._rawPointer, ref _rawPointer, Length); + SpanHelper.CopyTo(ref JitHelpers.GetByRef(ref destination._rawPointer), ref JitHelpers.GetByRef(ref _rawPointer), _length); return true; } @@ -228,7 +231,7 @@ namespace System if ((uint)values._length > (uint)_length) ThrowHelper.ThrowArgumentOutOfRangeException(); - SpanHelper.CopyTo(ref _rawPointer, ref values._rawPointer, values.Length); + SpanHelper.CopyTo(ref JitHelpers.GetByRef(ref _rawPointer), ref JitHelpers.GetByRef(ref values._rawPointer), values._length); } } @@ -250,7 +253,7 @@ namespace System return new Span( ref JitHelpers.GetByRef(ref source._rawPointer), - checked((int)(source._length * JitHelpers.SizeOf()))); + checked((int)(source._length * Unsafe.SizeOf()))); } /// @@ -269,7 +272,7 @@ namespace System return new ReadOnlySpan( ref JitHelpers.GetByRef(ref source._rawPointer), - checked((int)(source._length * JitHelpers.SizeOf()))); + checked((int)(source._length * Unsafe.SizeOf()))); } /// @@ -294,7 +297,7 @@ namespace System return new Span( ref JitHelpers.GetByRef(ref source._rawPointer), - checked((int)(source._length * JitHelpers.SizeOf() / JitHelpers.SizeOf()))); + checked((int)(source._length * Unsafe.SizeOf() / Unsafe.SizeOf()))); } /// @@ -319,51 +322,47 @@ namespace System return new ReadOnlySpan( ref JitHelpers.GetByRef(ref source._rawPointer), - checked((int)(source._length * JitHelpers.SizeOf() / JitHelpers.SizeOf()))); + checked((int)(source._length * Unsafe.SizeOf() / Unsafe.SizeOf()))); } } internal static class SpanHelper { - internal static void CopyTo(ref IntPtr destination, ref IntPtr source, int elementsCount) + internal static unsafe void CopyTo(ref T destination, ref T source, int elementsCount) { if (elementsCount == 0) return; - ref T dest = ref JitHelpers.GetByRef(ref destination); - ref T src = ref JitHelpers.GetByRef(ref source); - if (JitHelpers.ByRefEquals(ref dest, ref src)) + if (Unsafe.AreSame(ref destination, ref source)) return; if (!JitHelpers.ContainsReferences()) { - unsafe + fixed (byte* pDestination = &Unsafe.As(ref destination)) { - Memmove((byte*)destination, (byte*)source, elementsCount); + fixed (byte* pSource = &Unsafe.As(ref source)) + { +#if BIT64 + Buffer.Memmove(pDestination, pSource, (ulong)elementsCount * (ulong)Unsafe.SizeOf()); +#else + Buffer.Memmove(pDestination, pSource, (uint)elementsCount * (uint)Unsafe.SizeOf()); +#endif + } } } else { - if (JitHelpers.ByRefLessThan(ref dest, ref src)) // copy forward + if (JitHelpers.ByRefLessThan(ref destination, ref source)) // copy forward { for (int i = 0; i < elementsCount; i++) - JitHelpers.AddByRef(ref dest, i) = JitHelpers.AddByRef(ref src, i); + Unsafe.Add(ref destination, i) = Unsafe.Add(ref source, i); } else // copy backward to avoid overlapping issues { for (int i = elementsCount - 1; i >= 0; i--) - JitHelpers.AddByRef(ref dest, i) = JitHelpers.AddByRef(ref src, i); + Unsafe.Add(ref destination, i) = Unsafe.Add(ref source, i); } } } - - private static unsafe void Memmove(byte* destination, byte* source, int elementsCount) - { -#if BIT64 - Buffer.Memmove(destination, source, (ulong)elementsCount * (ulong)JitHelpers.SizeOf()); -#else - Buffer.Memmove(destination, source, (uint)elementsCount * (uint)JitHelpers.SizeOf()); -#endif - } } -} \ No newline at end of file +} diff --git a/src/coreclr/src/vm/jitinterface.cpp b/src/coreclr/src/vm/jitinterface.cpp index 36c10a7..f7730dd 100644 --- a/src/coreclr/src/vm/jitinterface.cpp +++ b/src/coreclr/src/vm/jitinterface.cpp @@ -6934,41 +6934,6 @@ bool getILIntrinsicImplementation(MethodDesc * ftn, methInfo->options = (CorInfoOptions)0; return true; } - else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__ADD_BYREF)->GetMemberDef()) - { - mdToken tokGenericArg = FindGenericMethodArgTypeSpec(MscorlibBinder::GetModule()->GetMDImport()); - - static BYTE ilcode[] = { CEE_LDARG_1, - CEE_PREFIX1,(BYTE)CEE_SIZEOF,0,0,0,0, - CEE_CONV_I, - CEE_MUL, - CEE_LDARG_0, - CEE_ADD, - CEE_RET }; - - ilcode[3] = (BYTE)(tokGenericArg); - ilcode[4] = (BYTE)(tokGenericArg >> 8); - ilcode[5] = (BYTE)(tokGenericArg >> 16); - ilcode[6] = (BYTE)(tokGenericArg >> 24); - - methInfo->ILCode = const_cast(ilcode); - methInfo->ILCodeSize = sizeof(ilcode); - methInfo->maxStack = 2; - methInfo->EHcount = 0; - methInfo->options = (CorInfoOptions)0; - return true; - } - else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__BYREF_EQUALS)->GetMemberDef()) - { - // Compare the two arguments - static const BYTE ilcode[] = { CEE_LDARG_0, CEE_LDARG_1, CEE_PREFIX1, (BYTE)CEE_CEQ, CEE_RET }; - methInfo->ILCode = const_cast(ilcode); - methInfo->ILCodeSize = sizeof(ilcode); - methInfo->maxStack = 2; - methInfo->EHcount = 0; - methInfo->options = (CorInfoOptions)0; - return true; - } else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__BYREF_LESSTHAN)->GetMemberDef()) { // Compare the two arguments @@ -7000,24 +6965,6 @@ bool getILIntrinsicImplementation(MethodDesc * ftn, methInfo->options = (CorInfoOptions)0; return true; } - else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__SIZEOF)->GetMemberDef()) - { - _ASSERTE(ftn->HasMethodInstantiation()); - Instantiation inst = ftn->GetMethodInstantiation(); - - _ASSERTE(ftn->GetNumGenericMethodArgs() == 1); - mdToken tokGenericArg = FindGenericMethodArgTypeSpec(MscorlibBinder::GetModule()->GetMDImport()); - - static const BYTE ilcode[] = { CEE_PREFIX1, (BYTE)CEE_SIZEOF, (BYTE)(tokGenericArg), (BYTE)(tokGenericArg >> 8), (BYTE)(tokGenericArg >> 16), (BYTE)(tokGenericArg >> 24), - CEE_RET }; - - methInfo->ILCode = const_cast(ilcode); - methInfo->ILCodeSize = sizeof(ilcode); - methInfo->maxStack = 1; - methInfo->EHcount = 0; - methInfo->options = (CorInfoOptions)0; - return true; - } else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__CONTAINSREFERENCES)->GetMemberDef()) { _ASSERTE(ftn->HasMethodInstantiation()); @@ -7045,11 +6992,91 @@ bool getILIntrinsicImplementation(MethodDesc * ftn, methInfo->options = (CorInfoOptions)0; return true; } -#endif +#endif // FEATURE_SPAN_OF_T return false; } +#ifdef FEATURE_SPAN_OF_T +bool getILIntrinsicImplementationForUnsafe(MethodDesc * ftn, + CORINFO_METHOD_INFO * methInfo) +{ + STANDARD_VM_CONTRACT; + + // Precondition: ftn is a method in mscorlib + _ASSERTE(ftn->GetModule()->IsSystem()); + + mdMethodDef tk = ftn->GetMemberDef(); + + if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__SIZEOF)->GetMemberDef()) + { + _ASSERTE(ftn->HasMethodInstantiation()); + Instantiation inst = ftn->GetMethodInstantiation(); + + _ASSERTE(ftn->GetNumGenericMethodArgs() == 1); + mdToken tokGenericArg = FindGenericMethodArgTypeSpec(MscorlibBinder::GetModule()->GetMDImport()); + + static const BYTE ilcode[] = { CEE_PREFIX1, (BYTE)CEE_SIZEOF, (BYTE)(tokGenericArg), (BYTE)(tokGenericArg >> 8), (BYTE)(tokGenericArg >> 16), (BYTE)(tokGenericArg >> 24), + CEE_RET }; + + methInfo->ILCode = const_cast(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 1; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } + else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_AS)->GetMemberDef()) + { + // Return the argument that was passed in. + static const BYTE ilcode[] = { CEE_LDARG_0, CEE_RET }; + methInfo->ILCode = const_cast(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 1; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } + else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_ADD)->GetMemberDef()) + { + mdToken tokGenericArg = FindGenericMethodArgTypeSpec(MscorlibBinder::GetModule()->GetMDImport()); + + static BYTE ilcode[] = { CEE_LDARG_1, + CEE_PREFIX1,(BYTE)CEE_SIZEOF,0,0,0,0, + CEE_CONV_I, + CEE_MUL, + CEE_LDARG_0, + CEE_ADD, + CEE_RET }; + + ilcode[3] = (BYTE)(tokGenericArg); + ilcode[4] = (BYTE)(tokGenericArg >> 8); + ilcode[5] = (BYTE)(tokGenericArg >> 16); + ilcode[6] = (BYTE)(tokGenericArg >> 24); + + methInfo->ILCode = const_cast(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 2; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } + else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_ARE_SAME)->GetMemberDef()) + { + // Compare the two arguments + static const BYTE ilcode[] = { CEE_LDARG_0, CEE_LDARG_1, CEE_PREFIX1, (BYTE)CEE_CEQ, CEE_RET }; + methInfo->ILCode = const_cast(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 2; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } + + return false; +} +#endif // FEATURE_SPAN_OF_T + bool getILIntrinsicImplementationForVolatile(MethodDesc * ftn, CORINFO_METHOD_INFO * methInfo) { @@ -7230,6 +7257,12 @@ getMethodInfoHelper( { fILIntrinsic = getILIntrinsicImplementation(ftn, methInfo); } +#ifdef FEATURE_SPAN_OF_T + else if (MscorlibBinder::IsClass(pMT, CLASS__UNSAFE)) + { + fILIntrinsic = getILIntrinsicImplementationForUnsafe(ftn, methInfo); + } +#endif else if (MscorlibBinder::IsClass(pMT, CLASS__INTERLOCKED)) { fILIntrinsic = getILIntrinsicImplementationForInterlocked(ftn, methInfo); diff --git a/src/coreclr/src/vm/mscorlib.h b/src/coreclr/src/vm/mscorlib.h index a8bcd81..7d75e59 100644 --- a/src/coreclr/src/vm/mscorlib.h +++ b/src/coreclr/src/vm/mscorlib.h @@ -1347,14 +1347,19 @@ DEFINE_METHOD(JIT_HELPERS, UNSAFE_CAST_TO_STACKPTR,UnsafeCastToStackPoi #ifdef FEATURE_SPAN_OF_T DEFINE_METHOD(JIT_HELPERS, GET_BYREF, GetByRef, NoSig) DEFINE_METHOD(JIT_HELPERS, SET_BYREF, SetByRef, NoSig) -DEFINE_METHOD(JIT_HELPERS, ADD_BYREF, AddByRef, NoSig) -DEFINE_METHOD(JIT_HELPERS, BYREF_EQUALS, ByRefEquals, NoSig) DEFINE_METHOD(JIT_HELPERS, BYREF_LESSTHAN, ByRefLessThan, NoSig) DEFINE_METHOD(JIT_HELPERS, GET_ARRAY_DATA, GetArrayData, NoSig) -DEFINE_METHOD(JIT_HELPERS, SIZEOF, SizeOf, NoSig) DEFINE_METHOD(JIT_HELPERS, CONTAINSREFERENCES, ContainsReferences, NoSig) #endif +#ifdef FEATURE_SPAN_OF_T +DEFINE_CLASS(UNSAFE, CompilerServices, Unsafe) +DEFINE_METHOD(UNSAFE, SIZEOF, SizeOf, NoSig) +DEFINE_METHOD(UNSAFE, BYREF_AS, As, NoSig) +DEFINE_METHOD(UNSAFE, BYREF_ADD, Add, NoSig) +DEFINE_METHOD(UNSAFE, BYREF_ARE_SAME, AreSame, NoSig) +#endif + DEFINE_CLASS(INTERLOCKED, Threading, Interlocked) DEFINE_METHOD(INTERLOCKED, COMPARE_EXCHANGE_T, CompareExchange, GM_RefT_T_T_RetT) DEFINE_METHOD(INTERLOCKED, COMPARE_EXCHANGE_OBJECT,CompareExchange, SM_RefObject_Object_Object_RetObject) -- 2.7.4