internal static ref byte GetRawSzArrayData(this Array array) =>
ref Unsafe.As<RawArrayData>(array).Data;
+ // CLR arrays are laid out in memory as follows (multidimensional array bounds are optional):
+ // [ sync block || pMethodTable || num components || MD array bounds || array data .. ]
+ // ^ ^ ^ returned reference
+ // | \-- ref Unsafe.As<RawData>(array).Data
+ // \-- array
+ // The BaseSize of an array includes all the fields before the array data,
+ // including the sync block and method table. The reference to RawData.Data
+ // points at the number of components, skipping over these two pointer-sized fields.
+ // So substrate those from BaseSize before adding to the RawData.Data reference.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe ref byte GetRawArrayData(this Array array) =>
ref Unsafe.AddByteOffset(ref Unsafe.As<RawData>(array).Data, (nuint)GetObjectMethodTablePointer(array)->BaseSize - (nuint)(2 * sizeof(IntPtr)));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe bool ObjectHasComponentSize(object obj)
{
- // CLR objects are laid out in memory as follows.
- // [ pMethodTable || .. object data .. ]
- // ^-- the object reference points here
- //
- // The m_dwFlags field of the method table class will have its high bit set if the
+ // The Flags field of the method table class will have its high bit set if the
// method table has component size info stored somewhere. See member
// MethodTable:IsStringOrArray in src\vm\methodtable.h for full details.
- //
- // So in effect this method is the equivalent of
- // return ((MethodTable*)(*obj))->IsStringOrArray();
return (int)GetObjectMethodTablePointer(obj)->Flags < 0;
}
public uint BaseSize;
}
- // Given an object reference, returns its MethodTable* as an IntPtr.
+ // Given an object reference, returns its MethodTable*.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe MethodTable* GetObjectMethodTablePointer(object obj)
{
FCIMPLEND
-FCIMPL1(void*, ArrayNative::GetRawArrayData, ArrayBase* array)
-{
- FCALL_CONTRACT;
-
- VALIDATEOBJECT(array);
-
- _ASSERTE(array != NULL);
-
- return array->GetDataPtr();
-}
-FCIMPLEND
-
-
// array is GC protected by caller
void ArrayInitializeWorker(ARRAYBASEREF * arrayRef,
MethodTable* pArrayMT,
{
public:
static FCDECL1(INT32, GetRank, ArrayBase* pArray);
- static FCDECL1(void*, GetRawArrayData, ArrayBase* array);
static FCDECL2(INT32, GetLowerBound, ArrayBase* pArray, unsigned int dimension);
static FCDECL2(INT32, GetUpperBound, ArrayBase* pArray, unsigned int dimension);
static FCDECL2(INT32, GetLength, ArrayBase* pArray, unsigned int dimension);
// used when verfifying generic code.
// However verification is tied in with some codegen in the JITs, so give these
// the shared MT just in case.
- // This checks match precisely one in ParamTypeDesc::OwnsMethodTable
+ // This checks match precisely one in ParamTypeDesc::OwnsTemplateMethodTable
if (CorTypeInfo::IsGenericVariable(elemType)) {
// This is loading the canonical version of the array so we can override
OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
FCFuncElement("GetLowerBound", ArrayNative::GetLowerBound)
FCFuncElement("GetUpperBound", ArrayNative::GetUpperBound)
FCIntrinsicSig("GetLength", &gsig_IM_Int_RetInt, ArrayNative::GetLength, CORINFO_INTRINSIC_Array_GetDimLength)
- FCFuncElement("GetRawArrayData", ArrayNative::GetRawArrayData)
FCFuncElement("Initialize", ArrayNative::Initialize)
FCFuncElement("Copy", ArrayNative::ArrayCopy)
FCFuncElement("GetRawArrayGeometry", ArrayNative::GetRawArrayGeometry)
SVAL_DECL(INT32, s_arrayBoundsZero); // = 0
// What comes after this conceputally is:
- // TypeHandle elementType; Only present if the method table is shared among many types (arrays of pointers)
// INT32 bounds[rank]; The bounds are only present for Multidimensional arrays
// INT32 lowerBounds[rank]; Valid indexes are lowerBounds[i] <= index[i] < lowerBounds[i] + bounds[i]
INDEBUG(Verify());
}
-//private: TypeHandle m_Arg; // The type that is being modified
-
-
// placement new operator
void* operator new(size_t size, void* spot) { return (spot); }