Cleanup array related FCalls (#22097)
authorJan Kotas <jkotas@microsoft.com>
Sun, 20 Jan 2019 16:16:44 +0000 (08:16 -0800)
committerGitHub <noreply@github.com>
Sun, 20 Jan 2019 16:16:44 +0000 (08:16 -0800)
* Cleanup Array FCalls

* Disable outdated CoreFX tests

https://github.com/dotnet/corefx/pull/34700

22 files changed:
src/System.Private.CoreLib/Resources/Strings.resx
src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ArrayWithOffset.cs
src/System.Private.CoreLib/src/System/Array.cs
src/System.Private.CoreLib/src/System/Buffer.cs
src/System.Private.CoreLib/src/System/RtType.cs
src/System.Private.CoreLib/src/System/Runtime/CompilerServices/jithelpers.cs
src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
src/classlibnative/bcltype/arraynative.cpp
src/classlibnative/bcltype/arraynative.h
src/dlls/mscorrc/mscorrc.rc
src/dlls/mscorrc/resource.h
src/vm/comutilnative.cpp
src/vm/comutilnative.h
src/vm/ecalllist.h
src/vm/ilmarshalers.cpp
src/vm/jithelpers.cpp
src/vm/jitinterface.h
src/vm/marshalnative.cpp
src/vm/marshalnative.h
src/vm/metasig.h
src/vm/mscorlib.h
tests/CoreFX/CoreFX.issues.json

index c89f942..8e8dc28 100644 (file)
   <data name="InvalidOp_InvalidNewEnumVariant" xml:space="preserve">
     <value>The returned enumerator does not implement IEnumVARIANT.</value>
   </data>
+  <data name="Argument_NotIsomorphic" xml:space="preserve">
+    <value>Object contains non-primitive or non-blittable data.</value>
+  </data>
+  <data name="Argument_StructArrayTooLarge" xml:space="preserve">
+    <value>Array size exceeds addressing limitations.</value>
+  </data>
+  <data name="IndexOutOfRange_ArrayWithOffset" xml:space="preserve">
+    <value>ArrayWithOffset: offset exceeds array size.</value>
+  </data>
 </root>
index 3bef38a..eb2a2cb 100644 (file)
@@ -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;
     }
 }
index 41e8d79..3192ba9 100644 (file)
@@ -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
index 73e8bce..af94e8e 100644 (file)
@@ -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
index c1ace86..921c15e 100644 (file)
@@ -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()
index b8bb7c4..1080821 100644 (file)
@@ -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;
 
index 5e9fd31..5e1396b 100644 (file)
@@ -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
index a40aed5..eb5cfd9 100644 (file)
@@ -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
 
 
 
index 3b6d549..8161dec 100644 (file)
@@ -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);
index f324421..355c902 100644 (file)
@@ -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."
index 1b71333..500ee74 100644 (file)
 #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
index 15bde67..7ca48ff 100644 (file)
@@ -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)
index c604811..7f51e23 100644 (file)
@@ -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);
 
index 89ed6fa..5fce200 100644 (file)
@@ -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)
index ea39f94..7abfc01 100644 (file)
@@ -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
index e60ffae..d0e0b44 100644 (file)
@@ -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()
index 136888e..82bf31b 100644 (file)
@@ -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();
index e2b2482..95ff460 100644 (file)
@@ -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)
@@ -297,22 +329,6 @@ 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)
  */
 FCIMPL1(UINT32, MarshalNative::OffsetOfHelper, ReflectFieldObject *pFieldUNSAFE)
@@ -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>@todo: If the handle is pinned check the object type.</TODO>
     if (isPinned)
     {
         ValidatePinnedObject(objRef);
@@ -718,7 +647,6 @@ FCIMPL4(Object*, MarshalNative::GCHandleInternalCompareExchange, OBJECTHANDLE ha
     LPVOID ret = NULL;
     HELPER_METHOD_FRAME_BEGIN_RET_NOPOLL();
 
-    //<TODO>@todo: If the handle is pinned check the object type.</TODO>
     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 ***
 //====================================================================
index 85be41a..53a9966 100644 (file)
@@ -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
     //====================================================================
index cbac116..e8327fc 100644 (file)
@@ -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))))
index 94acf84..95819d9 100644 (file)
@@ -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)
index 972dcec..c8b3967 100644 (file)
                 {
                     "name": "System.Runtime.InteropServices.Tests.DispatchWrapperTests.Ctor_NullUnix_ThrowsPlatformNotSupportedException",
                     "reason": "outdated"
+                },
+                {
+                    "name": "System.Runtime.InteropServices.Tests.ArrayWithOffsetTests.Ctor_Array_Offset",
+                    "reason": "outdated"
                 }
             ]
         }