diff options
author | Jan Kotas <jkotas@microsoft.com> | 2019-01-20 08:16:44 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-20 08:16:44 -0800 |
commit | 170854b92017d709bc82d7631c6cb33dd7443078 (patch) | |
tree | e4d216f1b1be6d9207644e160f86af8846c02577 /src/System.Private.CoreLib/src/System | |
parent | 614966d1e179c32ce85df2791102847128390ca6 (diff) | |
download | coreclr-170854b92017d709bc82d7631c6cb33dd7443078.tar.gz coreclr-170854b92017d709bc82d7631c6cb33dd7443078.tar.bz2 coreclr-170854b92017d709bc82d7631c6cb33dd7443078.zip |
Cleanup array related FCalls (#22097)
* Cleanup Array FCalls
* Disable outdated CoreFX tests
https://github.com/dotnet/corefx/pull/34700
Diffstat (limited to 'src/System.Private.CoreLib/src/System')
5 files changed, 65 insertions, 51 deletions
diff --git a/src/System.Private.CoreLib/src/System/Array.cs b/src/System.Private.CoreLib/src/System/Array.cs index 41e8d794f5..3192ba96e2 100644 --- a/src/System.Private.CoreLib/src/System/Array.cs +++ b/src/System.Private.CoreLib/src/System/Array.cs @@ -555,7 +555,10 @@ namespace System public extern int GetLowerBound(int dimension); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern int GetDataPtrOffsetInternal(); + internal extern ref byte GetRawArrayData(); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern int GetElementSize(); // Number of elements in the Array. int ICollection.Count diff --git a/src/System.Private.CoreLib/src/System/Buffer.cs b/src/System.Private.CoreLib/src/System/Buffer.cs index 73e8bce7b8..af94e8e08d 100644 --- a/src/System.Private.CoreLib/src/System/Buffer.cs +++ b/src/System.Private.CoreLib/src/System/Buffer.cs @@ -60,15 +60,6 @@ namespace System return _ByteLength(array); } - // Gets a particular byte out of the array. The array must be an - // array of primitives. - // - // This essentially does the following: - // return ((byte*)array) + index. - // - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern byte _GetByte(Array array, int index); - public static byte GetByte(Array array, int index) { // Is the array present? @@ -80,21 +71,12 @@ namespace System throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(array)); // Is the index in valid range of the array? - if (index < 0 || index >= _ByteLength(array)) + if ((uint)index >= (uint)_ByteLength(array)) throw new ArgumentOutOfRangeException(nameof(index)); - return _GetByte(array, index); + return Unsafe.Add<byte>(ref array.GetRawArrayData(), index); } - // Sets a particular byte in an the array. The array must be an - // array of primitives. - // - // This essentially does the following: - // *(((byte*)array) + index) = value. - // - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void _SetByte(Array array, int index, byte value); - public static void SetByte(Array array, int index, byte value) { // Is the array present? @@ -106,11 +88,10 @@ namespace System throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(array)); // Is the index in valid range of the array? - if (index < 0 || index >= _ByteLength(array)) + if ((uint)index >= (uint)_ByteLength(array)) throw new ArgumentOutOfRangeException(nameof(index)); - // Make the FCall to do the work - _SetByte(array, index, value); + Unsafe.Add<byte>(ref array.GetRawArrayData(), index) = value; } // This is currently used by System.IO.UnmanagedMemoryStream diff --git a/src/System.Private.CoreLib/src/System/RtType.cs b/src/System.Private.CoreLib/src/System/RtType.cs index c1ace86f6a..921c15e25b 100644 --- a/src/System.Private.CoreLib/src/System/RtType.cs +++ b/src/System.Private.CoreLib/src/System/RtType.cs @@ -2614,11 +2614,7 @@ namespace System public override Type[] GetInterfaces() { RuntimeType[] candidates = Cache.GetInterfaceList(MemberListType.All, null); - Type[] interfaces = new Type[candidates.Length]; - for (int i = 0; i < candidates.Length; i++) - JitHelpers.UnsafeSetArrayElement(interfaces, i, candidates[i]); - - return interfaces; + return new ReadOnlySpan<Type>(candidates).ToArray(); } public override Type[] GetNestedTypes(BindingFlags bindingAttr) @@ -3430,11 +3426,7 @@ namespace System string[] ret = Enum.InternalGetNames(this); // Make a copy since we can't hand out the same array since users can modify them - string[] retVal = new string[ret.Length]; - - Array.Copy(ret, 0, retVal, 0, ret.Length); - - return retVal; + return new ReadOnlySpan<string>(ret).ToArray(); } public override Array GetEnumValues() diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/jithelpers.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/jithelpers.cs index b8bb7c4981..10808216b0 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/jithelpers.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/jithelpers.cs @@ -99,10 +99,6 @@ namespace System.Runtime.CompilerServices return x.CompareTo(y); } - // Set the given element in the array without any type or range checks - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern void UnsafeSetArrayElement(object[] target, int index, object element); - internal static ref byte GetRawData(this object obj) => ref Unsafe.As<RawData>(obj).Data; diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs index 5e9fd31081..5e1396b670 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs @@ -4,16 +4,23 @@ using System.Collections.Generic; using System.Reflection; -using System.Reflection.Emit; using System.Security; using System.Text; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; -using Win32Native = Microsoft.Win32.Win32Native; +using Microsoft.Win32; using System.Diagnostics; using System.Runtime.InteropServices.ComTypes; using System.StubHelpers; +using Internal.Runtime.CompilerServices; + +#if BIT64 +using nuint = System.UInt64; +#else +using nuint = System.UInt32; +#endif // BIT64 + namespace System.Runtime.InteropServices { /// <summary> @@ -238,15 +245,25 @@ namespace System.Runtime.InteropServices /// <summary> /// IMPORTANT NOTICE: This method does not do any verification on the array. - /// It must be used with EXTREME CAUTION since passing in an array that is - /// not pinned or in the fixed heap can cause unexpected results. + /// It must be used with EXTREME CAUTION since passing in invalid index or + /// an array that is not pinned can cause unexpected results. /// </summary> - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index); + public static unsafe IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index) + { + if (arr == null) + throw new ArgumentNullException(nameof(arr)); - public static IntPtr UnsafeAddrOfPinnedArrayElement<T>(T[] arr, int index) + void* pRawData = Unsafe.AsPointer(ref arr.GetRawArrayData()); + return (IntPtr)((byte*)pRawData + (uint)index * (nuint)arr.GetElementSize()); + } + + public static unsafe IntPtr UnsafeAddrOfPinnedArrayElement<T>(T[] arr, int index) { - return UnsafeAddrOfPinnedArrayElement((Array)arr, index); + if (arr == null) + throw new ArgumentNullException(nameof(arr)); + + void* pRawData = Unsafe.AsPointer(ref arr.GetRawSzArrayData()); + return (IntPtr)((byte*)pRawData + (uint)index * (nuint)Unsafe.SizeOf<T>()); } public static void Copy(int[] source, int startIndex, IntPtr destination, int length) @@ -289,8 +306,17 @@ namespace System.Runtime.InteropServices CopyToNative(source, startIndex, destination, length); } - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void CopyToNative(object source, int startIndex, IntPtr destination, int length); + private static unsafe void CopyToNative<T>(T[] source, int startIndex, IntPtr destination, int length) + { + if (source == null) + throw new ArgumentNullException(nameof(source)); + if (destination == IntPtr.Zero) + throw new ArgumentNullException(nameof(destination)); + + // The rest of the argument validation is done by CopyTo + + new Span<T>(source, startIndex, length).CopyTo(new Span<T>((void*)destination, length)); + } public static void Copy(IntPtr source, int[] destination, int startIndex, int length) { @@ -332,9 +358,22 @@ namespace System.Runtime.InteropServices CopyToManaged(source, destination, startIndex, length); } - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void CopyToManaged(IntPtr source, object destination, int startIndex, int length); - + private static unsafe void CopyToManaged<T>(IntPtr source, T[] destination, int startIndex, int length) + { + if (source == IntPtr.Zero) + throw new ArgumentNullException(nameof(source)); + if (destination == null) + throw new ArgumentNullException(nameof(destination)); + if (startIndex < 0) + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex); + if (length < 0) + throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum); + + // The rest of the argument validation is done by CopyTo + + new Span<T>((void*)source, length).CopyTo(new Span<T>(destination, startIndex, length)); + } + public static byte ReadByte(object ptr, int ofs) { return ReadValueSlow(ptr, ofs, (IntPtr nativeHome, int offset) => ReadByte(nativeHome, offset)); @@ -837,6 +876,9 @@ namespace System.Runtime.InteropServices public static void DestroyStructure<T>(IntPtr ptr) => DestroyStructure(ptr, typeof(T)); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool IsPinnable(object obj); + #if FEATURE_COMINTEROP /// <summary> /// Returns the HInstance for this module. Returns -1 if the module doesn't have |