diff options
author | Jan Kotas <jkotas@microsoft.com> | 2021-04-21 06:57:02 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-21 06:57:02 +0300 |
commit | 8c3180d932146b1a76600601c03082c6a81e1a53 (patch) | |
tree | 16a0a30f3ea5b8796bccf3cdb13d71e2d2dd1614 /src/coreclr/classlibnative | |
parent | a4b0a038df1bd3954234e25451340ca81efcf1cf (diff) |
Simplify non-generic ArrayEnumerator (#51351)
* Simplify non-generic ArrayEnumerator
* Implement GetFlattenedIndex for Mono
Diffstat (limited to 'src/coreclr/classlibnative')
-rw-r--r-- | src/coreclr/classlibnative/bcltype/arraynative.cpp | 117 | ||||
-rw-r--r-- | src/coreclr/classlibnative/bcltype/arraynative.h | 4 |
2 files changed, 54 insertions, 67 deletions
diff --git a/src/coreclr/classlibnative/bcltype/arraynative.cpp b/src/coreclr/classlibnative/bcltype/arraynative.cpp index 50e652b5b66..b0236e91870 100644 --- a/src/coreclr/classlibnative/bcltype/arraynative.cpp +++ b/src/coreclr/classlibnative/bcltype/arraynative.cpp @@ -954,54 +954,50 @@ Done: ; } FCIMPLEND - -FCIMPL4(void, ArrayNative::GetReference, ArrayBase* refThisUNSAFE, TypedByRef* elemRef, INT32 rank, INT32* pIndices) +FCIMPL2(Object*, ArrayNative::GetValue, ArrayBase* refThisUNSAFE, INT_PTR flattenedIndex) { CONTRACTL { FCALL_CHECK; - PRECONDITION(rank >= 0); } CONTRACTL_END; - // FC_GC_POLL not necessary. We poll for GC in Array.Rank that's always called - // right before this function - FC_GC_POLL_NOT_NEEDED(); + BASEARRAYREF refThis(refThisUNSAFE); - BASEARRAYREF refThis = (BASEARRAYREF) refThisUNSAFE; + TypeHandle arrayElementType = refThis->GetArrayElementTypeHandle(); - _ASSERTE(rank == (INT32)refThis->GetRank()); + // Legacy behavior + if (arrayElementType.IsTypeDesc()) + { + CorElementType elemtype = arrayElementType.AsTypeDesc()->GetInternalCorElementType(); + if (elemtype == ELEMENT_TYPE_PTR || elemtype == ELEMENT_TYPE_FNPTR) + FCThrowRes(kNotSupportedException, W("NotSupported_Type")); + } - SIZE_T Offset = 0; - const INT32 *pBoundsPtr = refThis->GetBoundsPtr(); + _ASSERTE((SIZE_T)flattenedIndex < refThis->GetNumComponents()); + void* pData = refThis->GetDataPtr() + flattenedIndex * refThis->GetComponentSize(); + OBJECTREF Obj; - if (rank == 1) + MethodTable* pElementTypeMT = arrayElementType.GetMethodTable(); + if (pElementTypeMT->IsValueType()) { - Offset = pIndices[0] - refThis->GetLowerBoundsPtr()[0]; - - // Bounds check each index - // Casting to unsigned allows us to use one compare for [0..limit-1] - if (((UINT32) Offset) >= ((UINT32) pBoundsPtr[0])) - FCThrowVoid(kIndexOutOfRangeException); + HELPER_METHOD_FRAME_BEGIN_RET_0(); + Obj = pElementTypeMT->Box(pData); + HELPER_METHOD_FRAME_END(); } else { - // Avoid redundant computation in GetLowerBoundsPtr - const INT32 *pLowerBoundsPtr = pBoundsPtr + rank; - _ASSERTE(refThis->GetLowerBoundsPtr() == pLowerBoundsPtr); - - SIZE_T Multiplier = 1; + Obj = ObjectToOBJECTREF(*((Object**)pData)); + } - for (int i = rank; i >= 1; i--) { - INT32 curIndex = pIndices[i-1] - pLowerBoundsPtr[i-1]; + return OBJECTREFToObject(Obj); +} +FCIMPLEND - // Bounds check each index - // Casting to unsigned allows us to use one compare for [0..limit-1] - if (((UINT32) curIndex) >= ((UINT32) pBoundsPtr[i-1])) - FCThrowVoid(kIndexOutOfRangeException); +FCIMPL3(void, ArrayNative::SetValue, ArrayBase* refThisUNSAFE, Object* objUNSAFE, INT_PTR flattenedIndex) +{ + FCALL_CONTRACT; - Offset += curIndex * Multiplier; - Multiplier *= pBoundsPtr[i-1]; - } - } + BASEARRAYREF refThis(refThisUNSAFE); + OBJECTREF obj(objUNSAFE); TypeHandle arrayElementType = refThis->GetArrayElementTypeHandle(); @@ -1012,72 +1008,60 @@ FCIMPL4(void, ArrayNative::GetReference, ArrayBase* refThisUNSAFE, TypedByRef* e if (elemtype == ELEMENT_TYPE_PTR || elemtype == ELEMENT_TYPE_FNPTR) FCThrowResVoid(kNotSupportedException, W("NotSupported_Type")); } -#ifdef _DEBUG - CorElementType elemtype = arrayElementType.GetInternalCorElementType(); - _ASSERTE(elemtype != ELEMENT_TYPE_PTR && elemtype != ELEMENT_TYPE_FNPTR); -#endif - elemRef->data = refThis->GetDataPtr() + (Offset * refThis->GetComponentSize()); - elemRef->type = arrayElementType; -} -FCIMPLEND + _ASSERTE((SIZE_T)flattenedIndex < refThis->GetNumComponents()); -FCIMPL2(void, ArrayNative::SetValue, TypedByRef * target, Object* objUNSAFE) -{ - FCALL_CONTRACT; - - OBJECTREF obj = ObjectToOBJECTREF(objUNSAFE); + MethodTable* pElementTypeMT = arrayElementType.GetMethodTable(); + PREFIX_ASSUME(NULL != pElementTypeMT); - TypeHandle thTarget(target->type); - - MethodTable* pTargetMT = thTarget.AsMethodTable(); - PREFIX_ASSUME(NULL != pTargetMT); + void* pData = refThis->GetDataPtr() + flattenedIndex * refThis->GetComponentSize(); if (obj == NULL) { // Null is the universal zero... - if (pTargetMT->IsValueType()) - InitValueClass(target->data,pTargetMT); + if (pElementTypeMT->IsValueType()) + InitValueClass(pData,pElementTypeMT); else - ClearObjectReference((OBJECTREF*)target->data); + ClearObjectReference((OBJECTREF*)pData); } else - if (thTarget == TypeHandle(g_pObjectClass)) + if (arrayElementType == TypeHandle(g_pObjectClass)) { // Everything is compatible with Object - SetObjectReference((OBJECTREF*)target->data,(OBJECTREF)obj); + SetObjectReference((OBJECTREF*)pData,(OBJECTREF)obj); } else - if (!pTargetMT->IsValueType()) + if (!pElementTypeMT->IsValueType()) { - if (ObjIsInstanceOfCached(OBJECTREFToObject(obj), thTarget) != TypeHandle::CanCast) + if (ObjIsInstanceOfCached(OBJECTREFToObject(obj), arrayElementType) != TypeHandle::CanCast) { - // target->data is protected by the caller - HELPER_METHOD_FRAME_BEGIN_1(obj); + HELPER_METHOD_FRAME_BEGIN_2(refThis, obj); - if (!ObjIsInstanceOf(OBJECTREFToObject(obj), thTarget)) + if (!ObjIsInstanceOf(OBJECTREFToObject(obj), arrayElementType)) COMPlusThrow(kInvalidCastException,W("InvalidCast_StoreArrayElement")); HELPER_METHOD_FRAME_END(); + + // Refresh pData in case GC moved objects around + pData = refThis->GetDataPtr() + flattenedIndex * refThis->GetComponentSize(); } - SetObjectReference((OBJECTREF*)target->data,obj); + SetObjectReference((OBJECTREF*)pData,obj); } else { // value class or primitive type - if (!pTargetMT->UnBoxInto(target->data, obj)) + if (!pElementTypeMT->UnBoxInto(pData, obj)) { - // target->data is protected by the caller - HELPER_METHOD_FRAME_BEGIN_1(obj); + HELPER_METHOD_FRAME_BEGIN_2(refThis, obj); ARG_SLOT value = 0; // Allow enum -> primitive conversion, disallow primitive -> enum conversion TypeHandle thSrc = obj->GetTypeHandle(); CorElementType srcType = thSrc.GetVerifierCorElementType(); - CorElementType targetType = thTarget.GetSignatureCorElementType(); + CorElementType targetType = arrayElementType.GetSignatureCorElementType(); if (!InvokeUtil::IsPrimitiveType(srcType) || !InvokeUtil::IsPrimitiveType(targetType)) COMPlusThrow(kInvalidCastException, W("InvalidCast_StoreArrayElement")); @@ -1085,8 +1069,11 @@ FCIMPL2(void, ArrayNative::SetValue, TypedByRef * target, Object* objUNSAFE) // Get a properly widened type InvokeUtil::CreatePrimitiveValue(targetType,srcType,obj,&value); + // Refresh pData in case GC moved objects around + pData = refThis->GetDataPtr() + flattenedIndex * refThis->GetComponentSize(); + UINT cbSize = CorTypeInfo::Size(targetType); - memcpyNoGCRefs(target->data, ArgSlotEndianessFixup(&value, cbSize), cbSize); + memcpyNoGCRefs(pData, ArgSlotEndianessFixup(&value, cbSize), cbSize); HELPER_METHOD_FRAME_END(); } diff --git a/src/coreclr/classlibnative/bcltype/arraynative.h b/src/coreclr/classlibnative/bcltype/arraynative.h index c5be8403a8e..af926d8e424 100644 --- a/src/coreclr/classlibnative/bcltype/arraynative.h +++ b/src/coreclr/classlibnative/bcltype/arraynative.h @@ -36,10 +36,10 @@ public: static FCDECL4(Object*, CreateInstance, void* elementTypeHandle, INT32 rank, INT32* pLengths, INT32* pBounds); // This method will return a TypedReference to the array element - static FCDECL4(void, GetReference, ArrayBase* refThisUNSAFE, TypedByRef* elemRef, INT32 rank, INT32* pIndices); + static FCDECL2(Object*, GetValue, ArrayBase* refThisUNSAFE, INT_PTR flattenedIndex); // This set of methods will set a value in an array - static FCDECL2(void, SetValue, TypedByRef* target, Object* objUNSAFE); + static FCDECL3(void, SetValue, ArrayBase* refThisUNSAFE, Object* objUNSAFE, INT_PTR flattenedIndex); // This method will initialize an array from a TypeHandle // to a field. |