<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>
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;
{
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;
}
}
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
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?
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?
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
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)
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()
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;
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>
/// <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)
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)
{
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));
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
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
{
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);
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."
#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
}
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)
// 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);
#endif // defined(FEATURE_COMINTEROP)
FCFuncEnd()
-FCFuncStart(gJitHelpers)
- FCFuncElement("UnsafeSetArrayElement", JitHelpers::UnsafeSetArrayElement)
-FCFuncEnd()
-
FCFuncStart(gCOMTypeHandleFuncs)
FCFuncElement("CreateInstance", RuntimeTypeHandle::CreateInstance)
FCFuncElement("CreateCaInstance", RuntimeTypeHandle::CreateCaInstance)
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)
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_
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)
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)
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)
FCFuncElement("GetOverlappedFromNative", GetOverlappedFromNative)
FCFuncEnd()
-FCFuncStart(gCompilerFuncs)
+FCFuncStart(gRuntimeHelpers)
FCFuncElement("GetObjectValue", ObjectNative::GetObjectValue)
FCIntrinsic("InitializeArray", ArrayNative::InitializeArray, CORINFO_INTRINSIC_InitializeArray)
FCFuncElement("_RunClassConstructor", ReflectionInvocation::RunClassConstructor)
#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)
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)
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)
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);
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
//
//========================================================================
-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()
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();
}
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)
/************************************************************************
- * 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)
}
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
*/
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);
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);
}
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 ***
//====================================================================
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
//====================================================================
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))))
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)
{
"name": "System.Runtime.InteropServices.Tests.DispatchWrapperTests.Ctor_NullUnix_ThrowsPlatformNotSupportedException",
"reason": "outdated"
+ },
+ {
+ "name": "System.Runtime.InteropServices.Tests.ArrayWithOffsetTests.Ctor_Array_Offset",
+ "reason": "outdated"
}
]
}