From 170854b92017d709bc82d7631c6cb33dd7443078 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 20 Jan 2019 08:16:44 -0800 Subject: Cleanup array related FCalls (#22097) * Cleanup Array FCalls * Disable outdated CoreFX tests https://github.com/dotnet/corefx/pull/34700 --- src/System.Private.CoreLib/Resources/Strings.resx | 9 + .../Runtime/InteropServices/ArrayWithOffset.cs | 88 ++++------ src/System.Private.CoreLib/src/System/Array.cs | 5 +- src/System.Private.CoreLib/src/System/Buffer.cs | 27 +-- src/System.Private.CoreLib/src/System/RtType.cs | 12 +- .../System/Runtime/CompilerServices/jithelpers.cs | 4 - .../src/System/Runtime/InteropServices/Marshal.cs | 68 ++++++-- src/classlibnative/bcltype/arraynative.cpp | 16 +- src/classlibnative/bcltype/arraynative.h | 3 +- src/dlls/mscorrc/mscorrc.rc | 1 - src/dlls/mscorrc/resource.h | 2 +- src/vm/comutilnative.cpp | 31 ---- src/vm/comutilnative.h | 2 - src/vm/ecalllist.h | 28 +--- src/vm/ilmarshalers.cpp | 8 +- src/vm/jithelpers.cpp | 12 -- src/vm/jitinterface.h | 5 - src/vm/marshalnative.cpp | 182 ++++----------------- src/vm/marshalnative.h | 7 +- src/vm/metasig.h | 2 +- src/vm/mscorlib.h | 2 +- tests/CoreFX/CoreFX.issues.json | 4 + 22 files changed, 170 insertions(+), 348 deletions(-) diff --git a/src/System.Private.CoreLib/Resources/Strings.resx b/src/System.Private.CoreLib/Resources/Strings.resx index c89f9428b4..8e8dc28c4e 100644 --- a/src/System.Private.CoreLib/Resources/Strings.resx +++ b/src/System.Private.CoreLib/Resources/Strings.resx @@ -3655,4 +3655,13 @@ The returned enumerator does not implement IEnumVARIANT. + + Object contains non-primitive or non-blittable data. + + + Array size exceeds addressing limitations. + + + ArrayWithOffset: offset exceeds array size. + diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ArrayWithOffset.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ArrayWithOffset.cs index 3bef38a0b7..eb2a2cba14 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ArrayWithOffset.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ArrayWithOffset.cs @@ -4,19 +4,50 @@ using System.Runtime.CompilerServices; +#if BIT64 +using nuint = System.UInt64; +#else +using nuint = System.UInt32; +#endif + namespace System.Runtime.InteropServices { public struct ArrayWithOffset { + private object m_array; + private int m_offset; + private int m_count; + // From MAX_SIZE_FOR_INTEROP in mlinfo.h private const int MaxSizeForInterop = 0x7ffffff0; public ArrayWithOffset(object array, int offset) { + int totalSize = 0; + if (array != null) + { + if (!(array is Array arrayObj) || (arrayObj.Rank != 1) || !Marshal.IsPinnable(arrayObj)) + { + throw new ArgumentException(SR.Argument_NotIsomorphic); + } + + nuint nativeTotalSize = (nuint)arrayObj.LongLength * (nuint)arrayObj.GetElementSize(); + if (nativeTotalSize > MaxSizeForInterop) + { + throw new ArgumentException(SR.Argument_StructArrayTooLarge); + } + + totalSize = (int)nativeTotalSize; + } + + if ((uint)offset > (uint)totalSize) + { + throw new IndexOutOfRangeException(SR.IndexOutOfRange_ArrayWithOffset); + } + m_array = array; m_offset = offset; - m_count = 0; - m_count = CalculateCount(); + m_count = totalSize - offset; } public object GetArray() => m_array; @@ -44,58 +75,5 @@ namespace System.Runtime.InteropServices { return !(a == b); } - -#if CORECLR // TODO: Cleanup - [MethodImpl(MethodImplOptions.InternalCall)] - private extern int CalculateCount(); -#else - private int CalculateCount() - { - if (m_array == null) - { - if (m_offset != 0) - { - throw new IndexOutOfRangeException(SR.IndexOutOfRange_ArrayWithOffset); - } - - return 0; - } - else - { - Array arrayObj = m_array as Array; - if (arrayObj == null) - { - throw new ArgumentException(SR.Argument_NotIsomorphic); - } - - if (arrayObj.Rank != 1) - { - throw new ArgumentException(SR.Argument_NotIsomorphic); - } - - if (!arrayObj.IsBlittable()) - { - throw new ArgumentException(SR.Argument_NotIsomorphic); - } - - int totalSize = checked(arrayObj.Length * arrayObj.GetElementSize()); - if (totalSize > MaxSizeForInterop) - { - throw new ArgumentException(SR.Argument_StructArrayTooLarge); - } - - if (m_offset > totalSize) - { - throw new IndexOutOfRangeException(SR.IndexOutOfRange_ArrayWithOffset); - } - - return totalSize - m_offset; - } - } -#endif // !CORECLR - - private object m_array; - private int m_offset; - private int m_count; } } 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(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(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(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(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(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 { /// @@ -238,15 +245,25 @@ namespace System.Runtime.InteropServices /// /// 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. /// - [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[] 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[] 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()); } 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[] 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(source, startIndex, length).CopyTo(new Span((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(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((void*)source, length).CopyTo(new Span(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(IntPtr ptr) => DestroyStructure(ptr, typeof(T)); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool IsPinnable(object obj); + #if FEATURE_COMINTEROP /// /// Returns the HInstance for this module. Returns -1 if the module doesn't have diff --git a/src/classlibnative/bcltype/arraynative.cpp b/src/classlibnative/bcltype/arraynative.cpp index a40aed5619..eb5cfd9340 100644 --- a/src/classlibnative/bcltype/arraynative.cpp +++ b/src/classlibnative/bcltype/arraynative.cpp @@ -133,21 +133,29 @@ FCIMPL1(INT64, ArrayNative::GetLongLengthNoRank, ArrayBase* array) FCIMPLEND -FCIMPL1(INT32, ArrayNative::GetDataPtrOffsetInternal, ArrayBase* array) +FCIMPL1(void*, ArrayNative::GetRawArrayData, ArrayBase* array) { FCALL_CONTRACT; VALIDATEOBJECT(array); - if (array == NULL) - FCThrow(kNullReferenceException); + _ASSERTE(array != NULL); - return ArrayBase::GetDataPtrOffset(array->GetMethodTable()); + return array->GetDataPtr(); } FCIMPLEND +FCIMPL1(INT32, ArrayNative::GetElementSize, ArrayBase* array) +{ + FCALL_CONTRACT; + + VALIDATEOBJECT(array); + _ASSERTE(array != NULL); + return (INT32)array->GetComponentSize(); +} +FCIMPLEND diff --git a/src/classlibnative/bcltype/arraynative.h b/src/classlibnative/bcltype/arraynative.h index 3b6d5495f3..8161deca83 100644 --- a/src/classlibnative/bcltype/arraynative.h +++ b/src/classlibnative/bcltype/arraynative.h @@ -26,7 +26,8 @@ class ArrayNative { public: static FCDECL1(INT32, GetRank, ArrayBase* pArray); - static FCDECL1(INT32, GetDataPtrOffsetInternal, ArrayBase* array); + static FCDECL1(void*, GetRawArrayData, ArrayBase* array); + static FCDECL1(INT32, GetElementSize, ArrayBase* array); static FCDECL2(INT32, GetLowerBound, ArrayBase* pArray, unsigned int dimension); static FCDECL2(INT32, GetUpperBound, ArrayBase* pArray, unsigned int dimension); static FCDECL1(INT32, GetLengthNoRank, ArrayBase* pArray); diff --git a/src/dlls/mscorrc/mscorrc.rc b/src/dlls/mscorrc/mscorrc.rc index f3244218f9..355c902233 100644 --- a/src/dlls/mscorrc/mscorrc.rc +++ b/src/dlls/mscorrc/mscorrc.rc @@ -821,7 +821,6 @@ BEGIN CORSECATTR_E_BAD_ACTION "Security custom attribute has invalid SecurityAction." IDS_EE_COPY_OUTOFRANGE "Requested range extends past the end of the array." - IDS_EE_ARRAYWITHOFFSETOVERFLOW "ArrayWithOffset: offset exceeds array size." IDS_EE_NOCUSTOMMARSHALER "A call to GetInstance() for custom marshaler '%1' returned null, which is not allowed." IDS_EE_SIZECONTROLOUTOFRANGE "Array size control parameter index is out of range." IDS_EE_SIZECONTROLBADTYPE "Array size control parameter type not supported." diff --git a/src/dlls/mscorrc/resource.h b/src/dlls/mscorrc/resource.h index 1b71333385..500ee74642 100644 --- a/src/dlls/mscorrc/resource.h +++ b/src/dlls/mscorrc/resource.h @@ -274,7 +274,7 @@ #define IDS_EE_NOTISOMORPHIC 0x17e1 #define IDS_EE_COPY_OUTOFRANGE 0x17e3 -#define IDS_EE_ARRAYWITHOFFSETOVERFLOW 0x17e5 + #define IDS_EE_NOCUSTOMMARSHALER 0x17e7 #define IDS_EE_SIZECONTROLOUTOFRANGE 0x17e8 #define IDS_EE_SIZECONTROLBADTYPE 0x17e9 diff --git a/src/vm/comutilnative.cpp b/src/vm/comutilnative.cpp index 15bde67f2f..7ca48ffc59 100644 --- a/src/vm/comutilnative.cpp +++ b/src/vm/comutilnative.cpp @@ -850,37 +850,6 @@ FCIMPL1(FC_BOOL_RET, Buffer::IsPrimitiveTypeArray, ArrayBase *arrayUNSAFE) } FCIMPLEND -// Gets a particular byte out of the array. The array can't be an array of Objects - it -// must be a primitive array. -FCIMPL2(FC_UINT8_RET, Buffer::GetByte, ArrayBase *arrayUNSAFE, INT32 index) -{ - FCALL_CONTRACT; - - _ASSERTE(arrayUNSAFE != NULL); - _ASSERTE(index >=0 && index < ((INT32)(arrayUNSAFE->GetComponentSize() * arrayUNSAFE->GetNumComponents()))); - - UINT8 bData = *((BYTE*)arrayUNSAFE->GetDataPtr() + index); - return bData; -} -FCIMPLEND - -// Sets a particular byte in an array. The array can't be an array of Objects - it -// must be a primitive array. -// -// Semantically the bData argment is of type BYTE but FCallCheckSignature expects the -// type to be UINT8 and raises an error if this isn't this case when -// COMPlus_ConsistencyCheck is set. -FCIMPL3(VOID, Buffer::SetByte, ArrayBase *arrayUNSAFE, INT32 index, UINT8 bData) -{ - FCALL_CONTRACT; - - _ASSERTE(arrayUNSAFE != NULL); - _ASSERTE(index >=0 && index < ((INT32)(arrayUNSAFE->GetComponentSize() * arrayUNSAFE->GetNumComponents()))); - - *((BYTE*)arrayUNSAFE->GetDataPtr() + index) = (BYTE) bData; -} -FCIMPLEND - // Returns the length in bytes of an array containing // primitive type elements FCIMPL1(INT32, Buffer::ByteLength, ArrayBase* arrayUNSAFE) diff --git a/src/vm/comutilnative.h b/src/vm/comutilnative.h index c604811c9e..7f51e23db2 100644 --- a/src/vm/comutilnative.h +++ b/src/vm/comutilnative.h @@ -80,8 +80,6 @@ public: // This method from one primitive array to another based // upon an offset into each an a byte count. static FCDECL5(VOID, BlockCopy, ArrayBase *src, int srcOffset, ArrayBase *dst, int dstOffset, int count); - static FCDECL2(FC_UINT8_RET, GetByte, ArrayBase *arrayUNSAFE, INT32 index); - static FCDECL3(VOID, SetByte, ArrayBase *arrayUNSAFE, INT32 index, UINT8 bData); static FCDECL1(FC_BOOL_RET, IsPrimitiveTypeArray, ArrayBase *arrayUNSAFE); static FCDECL1(INT32, ByteLength, ArrayBase *arrayUNSAFE); diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index 89ed6fa95e..5fce2000eb 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -220,10 +220,6 @@ FCFuncStart(gSystem_RuntimeType) #endif // defined(FEATURE_COMINTEROP) FCFuncEnd() -FCFuncStart(gJitHelpers) - FCFuncElement("UnsafeSetArrayElement", JitHelpers::UnsafeSetArrayElement) -FCFuncEnd() - FCFuncStart(gCOMTypeHandleFuncs) FCFuncElement("CreateInstance", RuntimeTypeHandle::CreateInstance) FCFuncElement("CreateCaInstance", RuntimeTypeHandle::CreateCaInstance) @@ -750,7 +746,8 @@ FCFuncStart(gArrayFuncs) FCIntrinsicSig("GetLength", &gsig_IM_Int_RetInt, ArrayNative::GetLength, CORINFO_INTRINSIC_Array_GetDimLength) FCFuncElement("get_Length", ArrayNative::GetLengthNoRank) FCFuncElement("get_LongLength", ArrayNative::GetLongLengthNoRank) - FCFuncElement("GetDataPtrOffsetInternal", ArrayNative::GetDataPtrOffsetInternal) + FCFuncElement("GetRawArrayData", ArrayNative::GetRawArrayData) + FCFuncElement("GetElementSize", ArrayNative::GetElementSize) FCFuncElement("Initialize", ArrayNative::Initialize) FCFuncElement("Copy", ArrayNative::ArrayCopy) FCFuncElement("GetRawArrayGeometry", ArrayNative::GetRawArrayGeometry) @@ -766,8 +763,6 @@ FCFuncEnd() FCFuncStart(gBufferFuncs) FCFuncElement("BlockCopy", Buffer::BlockCopy) - FCFuncElement("_GetByte", Buffer::GetByte) - FCFuncElement("_SetByte", Buffer::SetByte) FCFuncElement("IsPrimitiveTypeArray", Buffer::IsPrimitiveTypeArray) FCFuncElement("_ByteLength", Buffer::ByteLength) #ifdef _TARGET_ARM_ @@ -814,9 +809,10 @@ FCFuncStart(gInteropMarshalFuncs) FCFuncElement("SetLastWin32Error", MarshalNative::SetLastWin32Error) FCFuncElement("SizeOfHelper", MarshalNative::SizeOfClass) FCFuncElement("GetSystemMaxDBCSCharSize", MarshalNative::GetSystemMaxDBCSCharSize) + FCFuncElement("StructureToPtr", MarshalNative::StructureToPtr) FCFuncElement("PtrToStructureHelper", MarshalNative::PtrToStructureHelper) FCFuncElement("DestroyStructure", MarshalNative::DestroyStructure) - FCFuncElement("UnsafeAddrOfPinnedArrayElement", MarshalNative::FCUnsafeAddrOfPinnedArrayElement) + FCFuncElement("IsPinnable", MarshalNative::IsPinnable) FCFuncElement("GetExceptionCode", ExceptionNative::GetExceptionCode) FCFuncElement("GetExceptionPointers", ExceptionNative::GetExceptionPointers) QCFuncElement("GetHINSTANCE", COMModule::GetHINSTANCE) @@ -824,9 +820,6 @@ FCFuncStart(gInteropMarshalFuncs) FCFuncElement("OffsetOfHelper", MarshalNative::OffsetOfHelper) QCFuncElement("InternalPrelink", MarshalNative::Prelink) - FCFuncElement("CopyToNative", MarshalNative::CopyToNative) - FCFuncElement("CopyToManaged", MarshalNative::CopyToManaged) - FCFuncElement("StructureToPtr", MarshalNative::StructureToPtr) FCFuncElement("ThrowExceptionForHRInternal", MarshalNative::ThrowExceptionForHR) FCFuncElement("GetExceptionForHRInternal", MarshalNative::GetExceptionForHR) FCFuncElement("GetDelegateForFunctionPointerInternal", MarshalNative::GetDelegateForFunctionPointerInternal) @@ -873,15 +866,8 @@ FCFuncStart(gInteropNativeLibraryFuncs) QCFuncElement("GetSymbol", NativeLibraryNative::GetSymbol) FCFuncEnd() -FCFuncStart(gArrayWithOffsetFuncs) - FCFuncElement("CalculateCount", MarshalNative::CalculateCount) -FCFuncEnd() - #ifdef FEATURE_COMINTEROP - - - #ifdef FEATURE_COMINTEROP_MANAGED_ACTIVATION FCFuncStart(gRegistrationFuncs) FCFuncElement("RegisterTypeForComClientsNative", RegisterTypeForComClientsNative) @@ -952,7 +938,7 @@ FCFuncStart(gOverlappedFuncs) FCFuncElement("GetOverlappedFromNative", GetOverlappedFromNative) FCFuncEnd() -FCFuncStart(gCompilerFuncs) +FCFuncStart(gRuntimeHelpers) FCFuncElement("GetObjectValue", ObjectNative::GetObjectValue) FCIntrinsic("InitializeArray", ArrayNative::InitializeArray, CORINFO_INTRINSIC_InitializeArray) FCFuncElement("_RunClassConstructor", ReflectionInvocation::RunClassConstructor) @@ -1217,7 +1203,6 @@ FCClassElement("ApplicationModel", "System", gApplicationModelFuncs) #endif FCClassElement("ArgIterator", "System", gVarArgFuncs) FCClassElement("Array", "System", gArrayFuncs) -FCClassElement("ArrayWithOffset", "System.Runtime.InteropServices", gArrayWithOffsetFuncs) FCClassElement("Assembly", "System.Reflection", gAssemblyFuncs) FCClassElement("AssemblyBuilder", "System.Reflection.Emit", gAssemblyBuilderFuncs) @@ -1256,7 +1241,6 @@ FCClassElement("IReflect", "System.Reflection", gStdMngIReflectFuncs) FCClassElement("InterfaceMarshaler", "System.StubHelpers", gInterfaceMarshalerFuncs) #endif FCClassElement("Interlocked", "System.Threading", gInterlockedFuncs) -FCClassElement("JitHelpers", "System.Runtime.CompilerServices", gJitHelpers) FCClassElement("LoaderAllocatorScout", "System.Reflection", gLoaderAllocatorFuncs) FCClassElement("ManifestBasedResourceGroveler", "System.Resources", gManifestBasedResourceGrovelerFuncs) FCClassElement("Marshal", "System.Runtime.InteropServices", gInteropMarshalFuncs) @@ -1304,7 +1288,7 @@ FCClassElement("RuntimeAssembly", "System.Reflection", gRuntimeAssemblyFuncs) FCClassElement("RuntimeClass", "System.Runtime.InteropServices.WindowsRuntime", gRuntimeClassFuncs) #endif // FEATURE_COMINTEROP FCClassElement("RuntimeFieldHandle", "System", gCOMFieldHandleNewFuncs) -FCClassElement("RuntimeHelpers", "System.Runtime.CompilerServices", gCompilerFuncs) +FCClassElement("RuntimeHelpers", "System.Runtime.CompilerServices", gRuntimeHelpers) FCClassElement("RuntimeImports", "System.Runtime", gRuntimeImportsFuncs) FCClassElement("RuntimeMethodHandle", "System", gRuntimeMethodHandle) FCClassElement("RuntimeModule", "System.Reflection", gCOMModuleFuncs) diff --git a/src/vm/ilmarshalers.cpp b/src/vm/ilmarshalers.cpp index ea39f94fd4..7abfc019f3 100644 --- a/src/vm/ilmarshalers.cpp +++ b/src/vm/ilmarshalers.cpp @@ -3464,10 +3464,8 @@ void ILArrayWithOffsetMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCo EmitLoadNativeValue(pslILEmit); // dest pslILEmit->EmitLDLOC(m_dwPinnedLocalNum); + pslILEmit->EmitCALL(METHOD__ARRAY__GET_RAW_ARRAY_DATA, 1, 1); pslILEmit->EmitCONV_I(); - pslILEmit->EmitLDLOC(m_dwPinnedLocalNum); - pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1); - pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement EmitLoadManagedValue(pslILEmit); pslILEmit->EmitLDFLD(tokArrayWithOffset_m_offset); @@ -3510,10 +3508,8 @@ void ILArrayWithOffsetMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* ps pslILEmit->EmitSTLOC(m_dwPinnedLocalNum); pslILEmit->EmitLDLOC(m_dwPinnedLocalNum); + pslILEmit->EmitCALL(METHOD__ARRAY__GET_RAW_ARRAY_DATA, 1, 1); pslILEmit->EmitCONV_I(); - pslILEmit->EmitLDLOC(m_dwPinnedLocalNum); - pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1); - pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement pslILEmit->EmitLDLOC(m_dwOffsetLocalNum); pslILEmit->EmitADD(); // dest diff --git a/src/vm/jithelpers.cpp b/src/vm/jithelpers.cpp index e60ffaeca1..d0e0b4463b 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -5741,18 +5741,6 @@ Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame, PTR_VOID StubS // //======================================================================== -FCIMPL3(void, JitHelpers::UnsafeSetArrayElement, PtrArray* pPtrArrayUNSAFE, INT32 index, Object* objectUNSAFE) { - FCALL_CONTRACT; - - PTRARRAYREF pPtrArray = (PTRARRAYREF)pPtrArrayUNSAFE; - OBJECTREF object = (OBJECTREF)objectUNSAFE; - - _ASSERTE(index < (INT32)pPtrArray->GetNumComponents()); - - pPtrArray->SetAt(index, object); -} -FCIMPLEND - #ifdef _TARGET_ARM_ // This function is used from the FCallMemcpy for GC polling EXTERN_C VOID FCallMemCpy_GCPoll() diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index 136888e6c8..82bf31b65a 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -1707,11 +1707,6 @@ CORINFO_GENERIC_HANDLE JIT_GenericHandleWorker(MethodDesc *pMD, void ClearJitGenericHandleCache(AppDomain *pDomain); -class JitHelpers { -public: - static FCDECL3(void, UnsafeSetArrayElement, PtrArray* pPtrArray, INT32 index, Object* object); -}; - CORJIT_FLAGS GetDebuggerCompileFlags(Module* pModule, CORJIT_FLAGS flags); bool __stdcall TrackAllocationsEnabled(); diff --git a/src/vm/marshalnative.cpp b/src/vm/marshalnative.cpp index e2b248289b..95ff46001a 100644 --- a/src/vm/marshalnative.cpp +++ b/src/vm/marshalnative.cpp @@ -255,6 +255,38 @@ FCIMPL2(VOID, MarshalNative::DestroyStructure, LPVOID ptr, ReflectClassBaseObjec } FCIMPLEND +FCIMPL1(FC_BOOL_RET, MarshalNative::IsPinnable, Object* obj) +{ + FCALL_CONTRACT; + + VALIDATEOBJECT(obj); + + if (obj == NULL) + FC_RETURN_BOOL(TRUE); + + if (obj->GetMethodTable() == g_pStringClass) + FC_RETURN_BOOL(TRUE); + + if (obj->GetMethodTable()->IsArray()) + { + BASEARRAYREF asArray = (BASEARRAYREF)ObjectToOBJECTREF(obj); + if (CorTypeInfo::IsPrimitiveType(asArray->GetArrayElementType())) + FC_RETURN_BOOL(TRUE); + + TypeHandle th = asArray->GetArrayElementTypeHandle(); + if (!th.IsTypeDesc()) + { + MethodTable *pMT = th.AsMethodTable(); + if (pMT->IsValueType() && pMT->IsBlittable()) + FC_RETURN_BOOL(TRUE); + } + + FC_RETURN_BOOL(FALSE); + } + + FC_RETURN_BOOL(obj->GetMethodTable()->IsBlittable()); +} +FCIMPLEND /************************************************************************ * PInvoke.SizeOf(Class) @@ -296,22 +328,6 @@ FCIMPL2(UINT32, MarshalNative::SizeOfClass, ReflectClassBaseObject* refClassUNSA FCIMPLEND -/************************************************************************ - * PInvoke.UnsafeAddrOfPinnedArrayElement(Array arr, int index) - */ - -FCIMPL2(LPVOID, MarshalNative::FCUnsafeAddrOfPinnedArrayElement, ArrayBase *arr, INT32 index) -{ - FCALL_CONTRACT; - - if (!arr) - FCThrowArgumentNull(W("arr")); - - return (arr->GetDataPtr() + (index*arr->GetComponentSize())); -} -FCIMPLEND - - /************************************************************************ * PInvoke.OffsetOfHelper(Class, Field) */ @@ -474,92 +490,6 @@ FCIMPL0(UINT32, MarshalNative::GetSystemMaxDBCSCharSize) } FCIMPLEND - -/************************************************************************ - * Handles all PInvoke.Copy(array source, ....) methods. - */ -FCIMPL4(void, MarshalNative::CopyToNative, Object* psrcUNSAFE, INT32 startindex, LPVOID pdst, INT32 length) -{ - CONTRACTL - { - FCALL_CHECK; - PRECONDITION(CheckPointer(pdst, NULL_OK)); - } - CONTRACTL_END; - - // The BCL code guarantees that Array will be passed in - _ASSERTE(!psrcUNSAFE || psrcUNSAFE->GetMethodTable()->IsArray()); - - BASEARRAYREF psrc = (BASEARRAYREF)(OBJECTREF)psrcUNSAFE; - - HELPER_METHOD_FRAME_BEGIN_1(psrc); - - if (pdst == NULL) - COMPlusThrowArgumentNull(W("destination")); - if (psrc == NULL) - COMPlusThrowArgumentNull(W("source")); - - SIZE_T numelem = psrc->GetNumComponents(); - - if (startindex < 0 || length < 0 || (SIZE_T)startindex + (SIZE_T)length > numelem) - { - COMPlusThrow(kArgumentOutOfRangeException, IDS_EE_COPY_OUTOFRANGE); - } - - SIZE_T componentsize = psrc->GetComponentSize(); - - memcpyNoGCRefs(pdst, - componentsize*startindex + (BYTE*)(psrc->GetDataPtr()), - componentsize*length); - - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - -FCIMPL4(void, MarshalNative::CopyToManaged, LPVOID psrc, Object* pdstUNSAFE, INT32 startindex, INT32 length) -{ - CONTRACTL - { - FCALL_CHECK; - PRECONDITION(CheckPointer(psrc, NULL_OK)); - } - CONTRACTL_END; - - // The BCL code guarantees that Array will be passed in - _ASSERTE(!pdstUNSAFE || pdstUNSAFE->GetMethodTable()->IsArray()); - - BASEARRAYREF pdst = (BASEARRAYREF)(OBJECTREF)pdstUNSAFE; - - HELPER_METHOD_FRAME_BEGIN_1(pdst); - - if (pdst == NULL) - COMPlusThrowArgumentNull(W("destination")); - if (psrc == NULL) - COMPlusThrowArgumentNull(W("source")); - if (startindex < 0) - COMPlusThrowArgumentOutOfRange(W("startIndex"), W("ArgumentOutOfRange_Count")); - if (length < 0) - COMPlusThrowArgumentOutOfRange(W("length"), W("ArgumentOutOfRange_NeedNonNegNum")); - - SIZE_T numelem = pdst->GetNumComponents(); - - if ((SIZE_T)startindex + (SIZE_T)length > numelem) - { - COMPlusThrow(kArgumentOutOfRangeException, IDS_EE_COPY_OUTOFRANGE); - } - - SIZE_T componentsize = pdst->GetComponentSize(); - - _ASSERTE(CorTypeInfo::IsPrimitiveType(pdst->GetArrayElementTypeHandle().GetInternalCorElementType())); - memcpyNoGCRefs(componentsize*startindex + (BYTE*)(pdst->GetDataPtr()), - psrc, - componentsize*length); - - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - - /************************************************************************ * PInvoke.GetLastWin32Error */ @@ -696,7 +626,6 @@ FCIMPL3(VOID, MarshalNative::GCHandleInternalSet, OBJECTHANDLE handle, Object *o OBJECTREF objRef(obj); HELPER_METHOD_FRAME_BEGIN_1(objRef); - //@todo: If the handle is pinned check the object type. if (isPinned) { ValidatePinnedObject(objRef); @@ -718,7 +647,6 @@ FCIMPL4(Object*, MarshalNative::GCHandleInternalCompareExchange, OBJECTHANDLE ha LPVOID ret = NULL; HELPER_METHOD_FRAME_BEGIN_RET_NOPOLL(); - //@todo: If the handle is pinned check the object type. if (isPinned) ValidatePinnedObject(newObjref); @@ -766,52 +694,6 @@ FCIMPL1(INT32, MarshalNative::GCHandleInternalGetHandleType, OBJECTHANDLE handle } FCIMPLEND -FCIMPL1(INT32, MarshalNative::CalculateCount, ArrayWithOffsetData* pArrayWithOffset) -{ - FCALL_CONTRACT; - - INT32 uRetVal = 0; - BASEARRAYREF arrayObj = pArrayWithOffset->m_Array; - HELPER_METHOD_FRAME_BEGIN_RET_1(arrayObj); - - SIZE_T cbTotalSize = 0; - - if (arrayObj != NULL) - { - if (!(arrayObj->GetMethodTable()->IsArray())) - COMPlusThrow(kArgumentException, IDS_EE_NOTISOMORPHIC); - if (arrayObj->GetMethodTable()->IsMultiDimArray()) - COMPlusThrow(kArgumentException, IDS_EE_NOTISOMORPHIC); - - ValidatePinnedObject(arrayObj); - } - - if (arrayObj == NULL) - { - if (pArrayWithOffset->m_cbOffset != 0) - COMPlusThrow(kIndexOutOfRangeException, IDS_EE_ARRAYWITHOFFSETOVERFLOW); - - goto lExit; - } - - cbTotalSize = arrayObj->GetNumComponents() * arrayObj->GetComponentSize(); - - if (cbTotalSize > MAX_SIZE_FOR_INTEROP) - COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE); - - if (pArrayWithOffset->m_cbOffset > (INT32)cbTotalSize) - COMPlusThrow(kIndexOutOfRangeException, IDS_EE_ARRAYWITHOFFSETOVERFLOW); - - uRetVal = (INT32)cbTotalSize - pArrayWithOffset->m_cbOffset; - _ASSERTE(uRetVal >= 0); - -lExit: ; - HELPER_METHOD_FRAME_END(); - return uRetVal; -} -FCIMPLEND - - //==================================================================== // *** Interop Helpers *** //==================================================================== diff --git a/src/vm/marshalnative.h b/src/vm/marshalnative.h index 85be41a86b..53a9966218 100644 --- a/src/vm/marshalnative.h +++ b/src/vm/marshalnative.h @@ -49,21 +49,18 @@ public: static FCDECL1(int, GetHRForException, Object* eUNSAFE); static FCDECL1(int, GetHRForException_WinRT, Object* eUNSAFE); - static FCDECL4(void, CopyToNative, Object* psrcUNSAFE, INT32 startindex, LPVOID pdst, INT32 length); - static FCDECL4(void, CopyToManaged, LPVOID psrc, Object* pdstUNSAFE, INT32 startindex, INT32 length); static FCDECL2(UINT32, SizeOfClass, ReflectClassBaseObject* refClass, CLR_BOOL throwIfNotMarshalable); - static FCDECL2(LPVOID, FCUnsafeAddrOfPinnedArrayElement, ArrayBase *arr, INT32 index); - static FCDECL1(UINT32, OffsetOfHelper, ReflectFieldObject* pFieldUNSAFE); static FCDECL0(int, GetLastWin32Error); static FCDECL1(void, SetLastWin32Error, int error); - static FCDECL1(INT32, CalculateCount, ArrayWithOffsetData* pRef); static FCDECL3(VOID, StructureToPtr, Object* pObjUNSAFE, LPVOID ptr, CLR_BOOL fDeleteOld); static FCDECL3(VOID, PtrToStructureHelper, LPVOID ptr, Object* pObjIn, CLR_BOOL allowValueClasses); static FCDECL2(VOID, DestroyStructure, LPVOID ptr, ReflectClassBaseObject* refClassUNSAFE); + static FCDECL1(FC_BOOL_RET, IsPinnable, Object* obj); + //==================================================================== // map a fiber cookie from the hosting APIs into a managed Thread object //==================================================================== diff --git a/src/vm/metasig.h b/src/vm/metasig.h index cbac116bd3..e8327fc020 100644 --- a/src/vm/metasig.h +++ b/src/vm/metasig.h @@ -515,7 +515,7 @@ DEFINE_METASIG_T(SM(RuntimeTypeHandle_RetIntPtr, g(RT_TYPE_HANDLE), I)) DEFINE_METASIG_T(SM(RuntimeMethodHandle_RetIntPtr, g(METHOD_HANDLE), I)) DEFINE_METASIG_T(SM(IntPtr_Type_RetDelegate, I C(TYPE), C(DELEGATE))) - +DEFINE_METASIG(IM(RetRefByte, _, r(b))) DEFINE_METASIG_T(IM(Type_RetArrObj, C(TYPE) F, a(j))) DEFINE_METASIG(IM(Bool_RetVoid, F, v)) DEFINE_METASIG_T(IM(BindingFlags_RetArrFieldInfo, g(BINDING_FLAGS), a(C(FIELD_INFO)))) diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index 94acf84f58..95819d95b6 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -92,7 +92,7 @@ DEFINE_CLASS(ARGUMENT_HANDLE, System, RuntimeArgumentHandl DEFINE_CLASS(ARRAY, System, Array) DEFINE_PROPERTY(ARRAY, LENGTH, Length, Int) -DEFINE_METHOD(ARRAY, GET_DATA_PTR_OFFSET_INTERNAL, GetDataPtrOffsetInternal, IM_RetInt) +DEFINE_METHOD(ARRAY, GET_RAW_ARRAY_DATA, GetRawArrayData, IM_RetRefByte) DEFINE_CLASS(ARRAY_WITH_OFFSET, Interop, ArrayWithOffset) DEFINE_FIELD(ARRAY_WITH_OFFSET, M_ARRAY, m_array) diff --git a/tests/CoreFX/CoreFX.issues.json b/tests/CoreFX/CoreFX.issues.json index 972dcec53f..c8b39676ad 100644 --- a/tests/CoreFX/CoreFX.issues.json +++ b/tests/CoreFX/CoreFX.issues.json @@ -830,6 +830,10 @@ { "name": "System.Runtime.InteropServices.Tests.DispatchWrapperTests.Ctor_NullUnix_ThrowsPlatformNotSupportedException", "reason": "outdated" + }, + { + "name": "System.Runtime.InteropServices.Tests.ArrayWithOffsetTests.Ctor_Array_Offset", + "reason": "outdated" } ] } -- cgit v1.2.3