diff --git a/docs/design/datacontracts/RuntimeTypeSystem.md b/docs/design/datacontracts/RuntimeTypeSystem.md index 0ce6cca2e5a141..d79e13ccb4da56 100644 --- a/docs/design/datacontracts/RuntimeTypeSystem.md +++ b/docs/design/datacontracts/RuntimeTypeSystem.md @@ -301,7 +301,7 @@ internal partial struct RuntimeTypeSystem_1 Category_Array = 0x00080000, Category_ValueType = 0x00040000, Category_Nullable = 0x00050000, - Category_PrimitiveValueType = 0x00060000, + Category_Primitive = 0x00060000, Category_TruePrimitive = 0x00070000, Category_Interface = 0x000C0000, Collectible = 0x00200000, @@ -822,7 +822,7 @@ Contracts used: return CorElementType.SzArray; case WFLAGS_HIGH.Category_ValueType: case WFLAGS_HIGH.Category_Nullable: - case WFLAGS_HIGH.Category_PrimitiveValueType: + case WFLAGS_HIGH.Category_Primitive: return CorElementType.ValueType; case WFLAGS_HIGH.Category_TruePrimitive: return (CorElementType)GetClassData(typeHandle).InternalCorElementType; @@ -857,20 +857,16 @@ Contracts used: // if typedesc: check for CorElementType.ValueType } - // Enums have Category_PrimitiveValueType in their MethodTable flags and their + // Enums have Category_Primitive in their MethodTable flags and their // InternalCorElementType is a primitive type (I1, U1, I2, U2, I4, U4, I8, U8), - // not ValueType. Regular primitive value types (IntPtr/UIntPtr) have Category_TruePrimitive. + // not ValueType. Regular primitive value types (Int32, etc.) have Category_TruePrimitive. public bool IsEnum(TypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return false; - CorElementType sigType = GetSignatureCorElementType(typeHandle); - if (sigType != CorElementType.ValueType) - return false; - - CorElementType internalType = (CorElementType)GetClassData(typeHandle).InternalCorElementType; - return internalType != CorElementType.ValueType; + MethodTable methodTable = _methodTables[typeHandle.Address]; + return methodTable.Flags.GetFlag(WFLAGS_HIGH.Category_Mask) == WFLAGS_HIGH.Category_Primitive; } // return true if the TypeHandle represents an array, and set the rank to either 0 (if the type is not an array), or the rank number if it is. diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index 935ae133272fe7..c037c95e9f3fce 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -850,8 +850,8 @@ internal unsafe struct MethodTable private const uint enum_flag_Category_ValueType = 0x00040000; private const uint enum_flag_Category_Nullable = 0x00050000; private const uint enum_flag_Category_IsPrimitiveMask = 0x000E0000; - private const uint enum_flag_Category_PrimitiveValueType = 0x00060000; // sub-category of ValueType, Enum or primitive value type - private const uint enum_flag_Category_TruePrimitive = 0x00070000; // sub-category of ValueType, Primitive (ELEMENT_TYPE_I, etc.) + private const uint enum_flag_Category_Enum = 0x00060000; // sub-category of ValueType + private const uint enum_flag_Category_TruePrimitive = 0x00070000; // sub-category of ValueType. (Int32, etc.) private const uint enum_flag_Category_Array = 0x00080000; private const uint enum_flag_Category_Array_Mask = 0x000C0000; private const uint enum_flag_Category_ValueType_Mask = 0x000C0000; @@ -955,7 +955,7 @@ public int MultiDimensionalArrayRank public bool IsByRefLike => (Flags & (enum_flag_HasComponentSize | enum_flag_IsByRefLike)) == enum_flag_IsByRefLike; // Warning! UNLIKE the similarly named Reflection api, this method also returns "true" for Enums. - public bool IsPrimitive => (Flags & enum_flag_Category_IsPrimitiveMask) == enum_flag_Category_PrimitiveValueType; + public bool IsPrimitive => (Flags & enum_flag_Category_IsPrimitiveMask) == enum_flag_Category_Enum; public bool IsTruePrimitive => (Flags & enum_flag_Category_Mask) is enum_flag_Category_TruePrimitive; diff --git a/src/coreclr/vm/arraynative.cpp b/src/coreclr/vm/arraynative.cpp index c076c42ffa02c7..be42a36c0b764d 100644 --- a/src/coreclr/vm/arraynative.cpp +++ b/src/coreclr/vm/arraynative.cpp @@ -24,7 +24,7 @@ FCIMPL1(INT32, ArrayNative::GetCorElementTypeOfElementType, ArrayBase* arrayUNSA _ASSERTE(arrayUNSAFE != NULL); - return arrayUNSAFE->GetArrayElementTypeHandle().GetVerifierCorElementType(); + return arrayUNSAFE->GetArrayElementTypeHandle().GetInternalCorElementType(); } FCIMPLEND diff --git a/src/coreclr/vm/callingconvention.h b/src/coreclr/vm/callingconvention.h index 746464ca77f2c0..e618e9e432ca28 100644 --- a/src/coreclr/vm/callingconvention.h +++ b/src/coreclr/vm/callingconvention.h @@ -2435,7 +2435,7 @@ inline BOOL HasRetBuffArgUnmanagedFixup(MetaSig * pSig) { WRAPPER_NO_CONTRACT; // We cannot just pSig->GetReturnType() here since it will return ELEMENT_TYPE_VALUETYPE for enums - CorElementType type = pSig->GetRetTypeHandleThrowing().GetVerifierCorElementType(); + CorElementType type = pSig->GetRetTypeHandleThrowing().GetInternalCorElementType(); return type == ELEMENT_TYPE_VALUETYPE; } #endif diff --git a/src/coreclr/vm/class.cpp b/src/coreclr/vm/class.cpp index 1a37e2346b0dbe..d5cbd54c028dc4 100644 --- a/src/coreclr/vm/class.cpp +++ b/src/coreclr/vm/class.cpp @@ -1318,7 +1318,7 @@ void ClassLoader::LoadExactParents(MethodTable* pMT) /*static*/ CorElementType ClassLoader::GetReducedTypeElementType(TypeHandle hType) { - CorElementType elemType = hType.GetVerifierCorElementType(); + CorElementType elemType = hType.GetInternalCorElementType(); switch (elemType) { case ELEMENT_TYPE_U1: diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index a4eb59dd72f4a0..24d4bf7140fb95 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -2511,7 +2511,7 @@ static bool IsLocationAssignable(TypeHandle fromHandle, TypeHandle toHandle, boo else { // they are not compatible yet enums can go into each other if their underlying element type is the same - if (toHandle.GetVerifierCorElementType() == fromHandle.GetVerifierCorElementType() + if (toHandle.GetInternalCorElementType() == fromHandle.GetInternalCorElementType() && (toHandle.IsEnum() || fromHandle.IsEnum())) return true; diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index bcbb0c6d8bfd9c..8db3217f1cb855 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -1977,7 +1977,7 @@ FCIMPL1(CorElementType, MethodTableNative::GetPrimitiveCorElementType, MethodTab { FCALL_CONTRACT; - _ASSERTE(mt->IsTruePrimitive() || mt->IsEnum()); + _ASSERTE(mt->IsPrimitive()); // MethodTable::GetInternalCorElementType has unnecessary overhead for primitives and enums // Call EEClass::GetInternalCorElementType directly to avoid it diff --git a/src/coreclr/vm/customattribute.cpp b/src/coreclr/vm/customattribute.cpp index caf204b84cee19..59c3d87f73b3d2 100644 --- a/src/coreclr/vm/customattribute.cpp +++ b/src/coreclr/vm/customattribute.cpp @@ -52,7 +52,7 @@ static HRESULT ParseCaType( if (!th.IsNull() && th.IsEnum()) { - pCaType->enumType = (CorSerializationType)th.GetVerifierCorElementType(); + pCaType->enumType = (CorSerializationType)th.GetInternalCorElementType(); // The assembly qualified name of th might not equal pCaType->szEnumName. // e.g. th could be "MyEnum, MyAssembly, Version=4.0.0.0" while diff --git a/src/coreclr/vm/ilmarshalers.cpp b/src/coreclr/vm/ilmarshalers.cpp index 110245fecc59a9..3c3b5d84a42b0d 100644 --- a/src/coreclr/vm/ilmarshalers.cpp +++ b/src/coreclr/vm/ilmarshalers.cpp @@ -3868,9 +3868,7 @@ bool ILNativeArrayMarshaler::CanMarshalViaPinning() TypeHandle elementTypeHandle = m_pargs->na.m_pArrayMT->GetArrayElementTypeHandle(); - return elementTypeHandle.IsBlittable() - && (elementTypeHandle.GetMethodTable()->IsValueType() - || elementTypeHandle.GetMethodTable()->IsTruePrimitive()); + return elementTypeHandle.IsBlittable() && elementTypeHandle.GetMethodTable()->IsValueType(); } void ILNativeArrayMarshaler::EmitMarshalViaPinning(ILCodeStream* pslILEmit) diff --git a/src/coreclr/vm/invokeutil.cpp b/src/coreclr/vm/invokeutil.cpp index ea289619bcf902..49186d28afc058 100644 --- a/src/coreclr/vm/invokeutil.cpp +++ b/src/coreclr/vm/invokeutil.cpp @@ -135,7 +135,7 @@ void InvokeUtil::CopyArg(TypeHandle th, PVOID argRef, ArgDestination *argDest) { CONTRACTL_END; void *pArgDst = argDest->GetDestinationAddress(); - CorElementType type = th.GetVerifierCorElementType(); + CorElementType type = th.GetInternalCorElementType(); switch (type) { #ifdef TARGET_RISCV64 @@ -500,7 +500,7 @@ void InvokeUtil::ValidField(TypeHandle th, OBJECTREF* value) if (th.IsEnum()) COMPlusThrow(kArgumentException,W("Arg_ObjObj")); - type = th.GetVerifierCorElementType(); + type = th.GetInternalCorElementType(); if (IsPrimitiveType(type)) { if (CanPrimitiveWiden(type, oType)) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 104bfc701e4872..bbe830f214e7da 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -343,14 +343,7 @@ CorInfoType CEEInfo::asCorInfoType(CorElementType eeType, // Enums are exactly like primitives, even from a verification standpoint, // so we zap the type handle in this case. // - // However RuntimeTypeHandle etc. are reported as E_T_INT (or something like that) - // but don't count as primitives as far as verification is concerned... - // - // To make things stranger, TypedReference returns true for "IsTruePrimitive". - // However the JIT likes us to report the type handle in that case. - if (!typeHnd.IsTypeDesc() && ( - (typeHnd.AsMethodTable()->IsTruePrimitive() && typeHnd != TypeHandle(g_TypedReferenceMT)) - || typeHnd.AsMethodTable()->IsEnum()) ) + if (!typeHnd.IsTypeDesc() && typeHnd.AsMethodTable()->IsPrimitive()) { typeHndUpdated = TypeHandle(); } @@ -377,10 +370,10 @@ CorInfoType CEEInfo::asCorInfoType(CorElementType eeType, CORINFO_TYPE_BYREF, CORINFO_TYPE_VALUECLASS, CORINFO_TYPE_CLASS, - CORINFO_TYPE_VAR, // VAR (type variable) + CORINFO_TYPE_VAR, // VAR CORINFO_TYPE_CLASS, // ARRAY - CORINFO_TYPE_CLASS, // WITH - CORINFO_TYPE_REFANY, + CORINFO_TYPE_CLASS, // GENERICINST + CORINFO_TYPE_VALUECLASS, // TypedReference CORINFO_TYPE_UNDEF, // VALUEARRAY_UNSUPPORTED CORINFO_TYPE_NATIVEINT, // I CORINFO_TYPE_NATIVEUINT, // U @@ -403,7 +396,7 @@ CorInfoType CEEInfo::asCorInfoType(CorElementType eeType, // spot check of the map _ASSERTE((CorInfoType) map[ELEMENT_TYPE_I4] == CORINFO_TYPE_INT); _ASSERTE((CorInfoType) map[ELEMENT_TYPE_PTR] == CORINFO_TYPE_PTR); - _ASSERTE((CorInfoType) map[ELEMENT_TYPE_TYPEDBYREF] == CORINFO_TYPE_REFANY); + _ASSERTE((CorInfoType) map[ELEMENT_TYPE_TYPEDBYREF] == CORINFO_TYPE_VALUECLASS); CorInfoType res = ((unsigned)eeType < ELEMENT_TYPE_MAX) ? ((CorInfoType) map[(unsigned)eeType]) : CORINFO_TYPE_UNDEF; @@ -4072,7 +4065,7 @@ CorInfoType CEEInfo::getTypeForPrimitiveValueClass( TypeHandle th(clsHnd); _ASSERTE (!th.IsGenericVariable()); - CorElementType elementType = th.GetVerifierCorElementType(); + CorElementType elementType = th.GetInternalCorElementType(); if (CorIsPrimitiveType(elementType)) { result = asCorInfoType(elementType); @@ -4450,7 +4443,7 @@ static bool isExactTypeHelper(TypeHandle th) th = pMT->GetArrayElementTypeHandle(); // Arrays of primitives are interchangeable with arrays of enums of the same underlying type. - if (CorTypeInfo::IsPrimitiveType(th.GetVerifierCorElementType())) + if (CorTypeInfo::IsPrimitiveType(th.GetInternalCorElementType())) return false; } @@ -5057,7 +5050,7 @@ void CEEInfo::getCallInfo( if (pMD->GetSlot() == CoreLibBinder::GetMethod(METHOD__OBJECT__GET_HASH_CODE)->GetSlot()) { // Pretend this was a "constrained. UnderlyingType" instruction prefix - constrainedType = TypeHandle(CoreLibBinder::GetElementType(constrainedType.GetVerifierCorElementType())); + constrainedType = TypeHandle(CoreLibBinder::GetElementType(constrainedType.GetInternalCorElementType())); constrainedResolvedTokenCopy = *pConstrainedResolvedToken; pConstrainedResolvedToken = &constrainedResolvedTokenCopy; @@ -7237,7 +7230,7 @@ static bool getILIntrinsicImplementationForInterlocked(MethodDesc * ftn, } else { - CorElementType elementType = typeHandle.GetVerifierCorElementType(); + CorElementType elementType = typeHandle.GetInternalCorElementType(); if (!CorTypeInfo::IsPrimitiveType(elementType) || elementType == ELEMENT_TYPE_R4 || elementType == ELEMENT_TYPE_R8) @@ -7406,7 +7399,7 @@ static bool getILIntrinsicImplementationForRuntimeHelpers( Instantiation inst = ftn->GetMethodInstantiation(); _ASSERTE(inst.GetNumArgs() == 1); - CorElementType et = inst[0].GetVerifierCorElementType(); + CorElementType et = inst[0].GetInternalCorElementType(); if (et == ELEMENT_TYPE_I4 || et == ELEMENT_TYPE_U4 || et == ELEMENT_TYPE_I2 || @@ -7435,7 +7428,7 @@ static bool getILIntrinsicImplementationForRuntimeHelpers( Instantiation inst = ftn->GetMethodInstantiation(); _ASSERTE(inst.GetNumArgs() == 1); - CorElementType et = inst[0].GetVerifierCorElementType(); + CorElementType et = inst[0].GetInternalCorElementType(); if (et == ELEMENT_TYPE_I4 || et == ELEMENT_TYPE_U4 || et == ELEMENT_TYPE_I2 || diff --git a/src/coreclr/vm/marshalnative.cpp b/src/coreclr/vm/marshalnative.cpp index b9163b700bad00..b63144baf8f916 100644 --- a/src/coreclr/vm/marshalnative.cpp +++ b/src/coreclr/vm/marshalnative.cpp @@ -110,7 +110,7 @@ extern "C" BOOL QCALLTYPE MarshalNative_HasLayout(QCall::TypeHandle t, BOOL* pIs { // Enums don't have native layout info, but they marshal identically // to their underlying primitive type. - th = CoreLibBinder::GetElementType(th.GetVerifierCorElementType()); + th = CoreLibBinder::GetElementType(th.GetInternalCorElementType()); } if (th.HasLayout()) diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 5a5a714a360edf..21aa442bdbfcf8 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -3087,7 +3087,7 @@ namespace STANDARD_VM_CONTRACT; PTR_MethodTable fieldType = pFieldDesc->GetFieldTypeHandleThrowing().GetMethodTable(); - CorElementType corType = fieldType->GetVerifierCorElementType(); + CorElementType corType = fieldType->GetInternalCorElementType(); if (corType == ELEMENT_TYPE_VALUETYPE) { @@ -4969,9 +4969,8 @@ CorElementType MethodTable::GetInternalCorElementType() ret = ELEMENT_TYPE_VALUETYPE; break; - case enum_flag_Category_PrimitiveValueType: - // This path should only be taken for the builtin CoreLib types - // and primitive valuetypes + case enum_flag_Category_Enum: + // enum_flag_Category_ElementTypeMask maps both Category_TruePrimitive and Category_Enum here. ret = GetClass()->GetInternalCorElementType(); _ASSERTE((ret != ELEMENT_TYPE_CLASS) && (ret != ELEMENT_TYPE_VALUETYPE)); @@ -4994,48 +4993,6 @@ CorElementType MethodTable::GetInternalCorElementType() return ret; } -//========================================================================================== -CorElementType MethodTable::GetVerifierCorElementType() -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - // This should not touch the EEClass, at least not in the - // common cases of ELEMENT_TYPE_CLASS and ELEMENT_TYPE_VALUETYPE. - CorElementType ret; - - switch (GetFlag(enum_flag_Category_ElementTypeMask)) - { - case enum_flag_Category_Array: - ret = ELEMENT_TYPE_ARRAY; - break; - - case enum_flag_Category_Array | enum_flag_Category_IfArrayThenSzArray: - ret = ELEMENT_TYPE_SZARRAY; - break; - - case enum_flag_Category_ValueType: - ret = ELEMENT_TYPE_VALUETYPE; - break; - - case enum_flag_Category_PrimitiveValueType: - // - // This is the only difference from MethodTable::GetInternalCorElementType() - // - if (IsTruePrimitive() || IsEnum()) - ret = GetClass()->GetInternalCorElementType(); - else - ret = ELEMENT_TYPE_VALUETYPE; - break; - - default: - ret = ELEMENT_TYPE_CLASS; - break; - } - - return ret; -} - //========================================================================================== CorElementType MethodTable::GetSignatureCorElementType() { @@ -5058,7 +5015,7 @@ CorElementType MethodTable::GetSignatureCorElementType() case enum_flag_Category_ValueType: case enum_flag_Category_Nullable: - case enum_flag_Category_PrimitiveValueType: + case enum_flag_Category_Enum: ret = ELEMENT_TYPE_VALUETYPE; break; @@ -5077,11 +5034,11 @@ CorElementType MethodTable::GetSignatureCorElementType() #ifndef DACCESS_COMPILE //========================================================================================== -void MethodTable::SetInternalCorElementType (CorElementType _NormType) +void MethodTable::SetInternalCorElementType(CorElementType elemType, bool isTruePrimitive) { WRAPPER_NO_CONTRACT; - switch (_NormType) + switch (elemType) { case ELEMENT_TYPE_CLASS: _ASSERTE(!IsArray()); @@ -5089,16 +5046,14 @@ void MethodTable::SetInternalCorElementType (CorElementType _NormType) break; case ELEMENT_TYPE_VALUETYPE: SetFlag(enum_flag_Category_ValueType); - _ASSERTE(GetFlag(enum_flag_Category_Mask) == enum_flag_Category_ValueType); break; default: - SetFlag(enum_flag_Category_PrimitiveValueType); - _ASSERTE(GetFlag(enum_flag_Category_Mask) == enum_flag_Category_PrimitiveValueType); + SetFlag(isTruePrimitive ? enum_flag_Category_TruePrimitive : enum_flag_Category_Enum); break; } - GetClass()->SetInternalCorElementType(_NormType); - _ASSERTE(GetInternalCorElementType() == _NormType); + GetClass()->SetInternalCorElementType(elemType); + _ASSERTE(GetInternalCorElementType() == elemType); } #endif // !DACCESS_COMPILE diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 402b0cde9b15bd..f4e8cf76174c98 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -2769,30 +2769,26 @@ class MethodTable // // #KindsOfElementTypes // GetInternalCorElementType() retrieves the internal representation of the type. It's not always - // appropriate to use this. For example, we treat enums as their underlying type or some structs are - // optimized to be ints. To get the signature type or the verifier type (same as signature except for - // enums are normalized to the primitive type that underlies them), use the APIs in Typehandle.h + // appropriate to use this. It treats enums as their underlying type. To get the signature + // type, use the APIs in Typehandle.h. // // * code:TypeHandle.GetSignatureCorElementType() - // * code:TypeHandle.GetVerifierCorElementType() // * code:TypeHandle.GetInternalCorElementType() CorElementType GetInternalCorElementType(); - void SetInternalCorElementType(CorElementType _NormType); - - // See code:TypeHandle::GetVerifierCorElementType for description - CorElementType GetVerifierCorElementType(); + void SetInternalCorElementType(CorElementType elemType, bool isTruePrimitive = false); // See code:TypeHandle::GetSignatureCorElementType for description CorElementType GetSignatureCorElementType(); - // A true primitive is one who's GetVerifierCorElementType() == + // A true primitive is one whose GetInternalCorElementType() == // ELEMENT_TYPE_I, // ELEMENT_TYPE_I4, - // ELEMENT_TYPE_TYPEDBYREF etc. - // Note that GetIntenalCorElementType might return these same values for some additional - // types such as Enums and some structs. - BOOL IsTruePrimitive(); - void SetIsTruePrimitive(); + // ELEMENT_TYPE_R8, etc. + // Note that IsTruePrimitive returns false for enum types. + bool IsTruePrimitive(); + + // Like IsTruePrimitive but also returns true for enum types. + bool IsPrimitive(); // Is this delegate? Returns false for System.Delegate and System.MulticastDelegate. inline BOOL IsDelegate() @@ -3793,8 +3789,8 @@ public : enum_flag_Category_ValueType = 0x00040000, // [cDAC] [RuntimeTypeSystem]: Contract depends on this value enum_flag_Category_ValueType_Mask = 0x000C0000, enum_flag_Category_Nullable = 0x00050000, // sub-category of ValueType. [cDAC] [RuntimeTypeSystem]: Contract depends on this value - enum_flag_Category_PrimitiveValueType=0x00060000, // sub-category of ValueType, Enum or primitive value type. [cDAC] [RuntimeTypeSystem]: Contract depends on this value - enum_flag_Category_TruePrimitive = 0x00070000, // sub-category of ValueType, Primitive (ELEMENT_TYPE_I, etc.). [cDAC] [RuntimeTypeSystem]: Contract depends on this value + enum_flag_Category_Enum = 0x00060000, // sub-category of ValueType. [cDAC] [RuntimeTypeSystem]: Contract depends on this value + enum_flag_Category_TruePrimitive = 0x00070000, // sub-category of ValueType. (Int32, etc.). [cDAC] [RuntimeTypeSystem]: Contract depends on this value enum_flag_Category_Array = 0x00080000, // [cDAC] [RuntimeTypeSystem]: Contract depends on this value enum_flag_Category_Array_Mask = 0x000C0000, // [cDAC] [RuntimeTypeSystem]: Contract depends on this value diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl index d0b112d01d7526..ec821ac7962ce4 100644 --- a/src/coreclr/vm/methodtable.inl +++ b/src/coreclr/vm/methodtable.inl @@ -324,17 +324,18 @@ inline DWORD MethodTable::GetRank() } //========================================================================================== -inline BOOL MethodTable::IsTruePrimitive() +inline bool MethodTable::IsTruePrimitive() { LIMITED_METHOD_DAC_CONTRACT; return GetFlag(enum_flag_Category_Mask) == enum_flag_Category_TruePrimitive; } //========================================================================================== -inline void MethodTable::SetIsTruePrimitive() +inline bool MethodTable::IsPrimitive() { LIMITED_METHOD_DAC_CONTRACT; - SetFlag(enum_flag_Category_TruePrimitive); + // enum_flag_Category_ElementTypeMask maps both Category_TruePrimitive and Category_Enum here. + return GetFlag(enum_flag_Category_ElementTypeMask) == enum_flag_Category_Enum; } //========================================================================================== diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 038fa7a8d61417..fb16290b29e561 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -4450,7 +4450,7 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, SetHasFieldsWhichMustBeInited(); #ifdef FEATURE_READYTORUN - if (!(pByValueClass->IsTruePrimitive() || pByValueClass->IsEnum())) + if (!pByValueClass->IsPrimitive()) { CheckLayoutDependsOnOtherModules(pByValueClass); } @@ -10742,10 +10742,9 @@ void MethodTableBuilder::CheckForSystemTypes() // Check if it is a primitive type CorElementType type = CorTypeInfo::FindPrimitiveType(name); - if (type != ELEMENT_TYPE_END) + if (type != ELEMENT_TYPE_END && CorTypeInfo::IsPrimitiveType(type)) { - pMT->SetInternalCorElementType(type); - pMT->SetIsTruePrimitive(); + pMT->SetInternalCorElementType(type, true); #if defined(TARGET_X86) && defined(UNIX_X86_ABI) switch (type) @@ -10778,18 +10777,6 @@ void MethodTableBuilder::CheckForSystemTypes() { pMT->SetIsNullable(); } - else if (strcmp(name, g_RuntimeArgumentHandleName) == 0) - { - pMT->SetInternalCorElementType (ELEMENT_TYPE_I); - } - else if (strcmp(name, g_RuntimeMethodHandleInternalName) == 0) - { - pMT->SetInternalCorElementType (ELEMENT_TYPE_I); - } - else if (strcmp(name, g_RuntimeFieldHandleInternalName) == 0) - { - pMT->SetInternalCorElementType (ELEMENT_TYPE_I); - } else if ((strcmp(name, g_Int128Name) == 0) || (strcmp(name, g_UInt128Name) == 0)) { EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo(); @@ -12031,7 +12018,7 @@ VOID MethodTableBuilder::CheckLayoutDependsOnOtherModules(MethodTable * pDepende STANDARD_VM_CONTRACT; // These cases are expected to be handled by the caller - _ASSERTE(!(pDependencyMT == g_pObjectClass || pDependencyMT->IsTruePrimitive() || ((g_pEnumClass != NULL) && pDependencyMT->IsEnum()))); + _ASSERTE(!(pDependencyMT == g_pObjectClass || pDependencyMT->IsPrimitive())); // // WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!! diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index 8869fd4f0397a4..9a88fbfe9380ce 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -1777,7 +1777,7 @@ HRESULT ProfToEEInterfaceImpl::IsArrayClass( // Fill in the type if they want it if (pBaseElemType != NULL) { - *pBaseElemType = th.GetArrayElementTypeHandle().GetVerifierCorElementType(); + *pBaseElemType = th.GetArrayElementTypeHandle().GetInternalCorElementType(); } // If this is an array of classes and they wish to have the base type diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp index 37343b4fcb9cc2..781b39252c72ba 100644 --- a/src/coreclr/vm/reflectioninvocation.cpp +++ b/src/coreclr/vm/reflectioninvocation.cpp @@ -63,7 +63,7 @@ extern "C" void QCALLTYPE RuntimeFieldHandle_SetValue(FieldDesc* fieldDesc, QCal GCPROTECT_BEGIN(gc); TypeHandle fieldTypeHandle = fieldType.AsTypeHandle(); - InvokeUtil::SetValidField(fieldTypeHandle.GetVerifierCorElementType(), fieldTypeHandle, fieldDesc, &gc.target, &gc.value, declaringType.AsTypeHandle(), pIsClassInitialized); + InvokeUtil::SetValidField(fieldTypeHandle.GetInternalCorElementType(), fieldTypeHandle, fieldDesc, &gc.target, &gc.value, declaringType.AsTypeHandle(), pIsClassInitialized); GCPROTECT_END(); END_QCALL; @@ -1989,7 +1989,7 @@ extern "C" void QCALLTYPE ReflectionInvocation_GetBoxInfo( MethodTable* pMT = type.AsMethodTable(); - _ASSERTE(pMT->IsValueType() || pMT->IsNullable() || pMT->IsEnum() || pMT->IsTruePrimitive()); + _ASSERTE(pMT->IsValueType()); *pValueOffset = 0; diff --git a/src/coreclr/vm/typedesc.cpp b/src/coreclr/vm/typedesc.cpp index 09598f362c7452..5b5c6f807c9c2c 100644 --- a/src/coreclr/vm/typedesc.cpp +++ b/src/coreclr/vm/typedesc.cpp @@ -401,7 +401,7 @@ BOOL TypeDesc::CanCastParam(TypeHandle fromParam, TypeHandle toParam, TypeHandle return TRUE; // Object parameters dont need an exact match but only inheritance, check for that - CorElementType fromParamCorType = fromParam.GetVerifierCorElementType(); + CorElementType fromParamCorType = fromParam.GetInternalCorElementType(); if (CorTypeInfo::IsObjRef(fromParamCorType)) { return fromParam.CanCastTo(toParam, pVisited); @@ -420,7 +420,7 @@ BOOL TypeDesc::CanCastParam(TypeHandle fromParam, TypeHandle toParam, TypeHandle } else if(CorTypeInfo::IsPrimitiveType(fromParamCorType)) { - CorElementType toParamCorType = toParam.GetVerifierCorElementType(); + CorElementType toParamCorType = toParam.GetInternalCorElementType(); if(CorTypeInfo::IsPrimitiveType(toParamCorType)) { if (GetNormalizedIntegralArrayElementType(toParamCorType) == GetNormalizedIntegralArrayElementType(fromParamCorType)) diff --git a/src/coreclr/vm/typehandle.cpp b/src/coreclr/vm/typehandle.cpp index 5dd7d4e85d468a..a1ddb5fca11010 100644 --- a/src/coreclr/vm/typehandle.cpp +++ b/src/coreclr/vm/typehandle.cpp @@ -592,7 +592,7 @@ BOOL TypeHandle::IsBoxedAndCanCastTo(TypeHandle type, TypeHandlePairList *pPairL CONTRACTL_END - CorElementType fromParamCorType = GetVerifierCorElementType(); + CorElementType fromParamCorType = GetInternalCorElementType(); if (CorTypeInfo::IsObjRef(fromParamCorType)) { @@ -1205,24 +1205,6 @@ CorElementType TypeHandle::GetSignatureCorElementType() const } } -// As its name suggests, this returns the type used by the IL verifier. The basic difference between this -// type and the type in the meta-data is that enumerations have been normalized to their underlieing -// primitive type. see code:MethodTable#KindsOfElementTypes for more -CorElementType TypeHandle::GetVerifierCorElementType() const -{ - LIMITED_METHOD_CONTRACT; - - if (IsTypeDesc()) - { - return AsTypeDesc()->GetInternalCorElementType(); - } - else - { - return AsMethodTable()->GetVerifierCorElementType(); - } -} - - #ifdef DACCESS_COMPILE void diff --git a/src/coreclr/vm/typehandle.h b/src/coreclr/vm/typehandle.h index 1fb2f944bb509d..6c10b2d755704d 100644 --- a/src/coreclr/vm/typehandle.h +++ b/src/coreclr/vm/typehandle.h @@ -200,26 +200,10 @@ class TypeHandle // This helper: // - Will return enums underlying type // - Will return underlying primitive for System.Int32 etc... - // - Will return underlying primitive as will be used in the calling convention - // For example - // struct t - // { - // public int i; - // } - // will return ELEMENT_TYPE_I4 in x86 instead of ELEMENT_TYPE_VALUETYPE. We - // call this type of value type a primitive value type // - // Internal representation is used among another things for the calling convention - // (jit benefits of primitive value types) or optimizing marshalling. - // - // This will NOT convert E_T_ARRAY, E_T_SZARRAY etc. to E_T_CLASS (though it probably - // should). Use CorTypeInfo::IsObjRef for that. + // This will NOT convert E_T_ARRAY, E_T_SZARRAY etc. to E_T_CLASS. Use CorTypeInfo::IsObjRef for that. CorElementType GetInternalCorElementType() const; - // This helper will return the same as GetSignatureCorElementType except: - // - Will return enums underlying type - CorElementType GetVerifierCorElementType() const; - //------------------------------------------------------------------- // CASTING // diff --git a/src/coreclr/vm/zapsig.cpp b/src/coreclr/vm/zapsig.cpp index d73e609a01936d..216bd28e360dcb 100644 --- a/src/coreclr/vm/zapsig.cpp +++ b/src/coreclr/vm/zapsig.cpp @@ -270,6 +270,8 @@ BOOL ZapSig::GetSignatureForTypeHandle(TypeHandle handle, elemType = ELEMENT_TYPE_OBJECT; else if (pMT == g_pStringClass) elemType = ELEMENT_TYPE_STRING; + else if (pMT == g_TypedReferenceMT) + elemType = ELEMENT_TYPE_TYPEDBYREF; else if (pMT == g_pCanonMethodTableClass) elemType = (CorElementType) ELEMENT_TYPE_CANON_ZAPSIG; else if (pMT->IsArray()) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs index cd9fb666c51962..18212c630216fb 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs @@ -854,7 +854,7 @@ public CorElementType GetSignatureCorElementType(TypeHandle typeHandle) return CorElementType.SzArray; case MethodTableFlags_1.WFLAGS_HIGH.Category_ValueType: case MethodTableFlags_1.WFLAGS_HIGH.Category_Nullable: - case MethodTableFlags_1.WFLAGS_HIGH.Category_PrimitiveValueType: + case MethodTableFlags_1.WFLAGS_HIGH.Category_Enum: return CorElementType.ValueType; case MethodTableFlags_1.WFLAGS_HIGH.Category_TruePrimitive: return (CorElementType)GetClassData(typeHandle).InternalCorElementType; @@ -902,18 +902,14 @@ public bool IsValueType(TypeHandle typeHandle) public bool IsEnum(TypeHandle typeHandle) { - // Enums have Category_PrimitiveValueType in their MethodTable flags and their + // Enums have Category_Enum in their MethodTable flags and their // InternalCorElementType is a primitive type (I1, U1, I2, U2, I4, U4, I8, U8), - // not ValueType. Regular primitive value types (IntPtr/UIntPtr) have Category_TruePrimitive. + // not ValueType. if (!typeHandle.IsMethodTable()) return false; - CorElementType sigType = GetSignatureCorElementType(typeHandle); - if (sigType != CorElementType.ValueType) - return false; - - CorElementType internalType = (CorElementType)GetClassData(typeHandle).InternalCorElementType; - return internalType != CorElementType.ValueType; + MethodTable methodTable = _methodTables[typeHandle.Address]; + return methodTable.Flags.GetFlag(MethodTableFlags_1.WFLAGS_HIGH.Category_Mask) == MethodTableFlags_1.WFLAGS_HIGH.Category_Enum; } // return true if the TypeHandle represents an array, and set the rank to either 0 (if the type is not an array), or the rank number if it is. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/MethodTableFlags_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/MethodTableFlags_1.cs index 466d45a4ee4975..11076a8c73a8d4 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/MethodTableFlags_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/MethodTableFlags_1.cs @@ -42,7 +42,7 @@ internal enum WFLAGS_HIGH : uint Category_ElementType_Mask = 0x000E0000, Category_ValueType = 0x00040000, Category_Nullable = 0x00050000, - Category_PrimitiveValueType = 0x00060000, + Category_Enum = 0x00060000, Category_TruePrimitive = 0x00070000, Category_Interface = 0x000C0000, Collectible = 0x00200000, // GC depends on this bit. diff --git a/src/native/managed/cdac/tests/MethodTableTests.cs b/src/native/managed/cdac/tests/MethodTableTests.cs index 6ceafece039de6..607332412efa83 100644 --- a/src/native/managed/cdac/tests/MethodTableTests.cs +++ b/src/native/managed/cdac/tests/MethodTableTests.cs @@ -571,7 +571,7 @@ public void IsValueTypeReturnsTrueForValueTypeCategories(MockTarget.Architecture { TargetPointer valueTypeMTPtr = default; TargetPointer nullableMTPtr = default; - TargetPointer primitiveValueTypeMTPtr = default; + TargetPointer enumMTPtr = default; TargetPointer truePrimitiveMTPtr = default; TestPlaceholderTarget target = CreateTarget( @@ -600,15 +600,15 @@ public void IsValueTypeReturnsTrueForValueTypeCategories(MockTarget.Architecture nullableMT.EEClassOrCanonMT = nullableEEClass.Address; nullableMTPtr = nullableMT.Address; - MockEEClass pvtEEClass = rtsBuilder.AddEEClass("PrimitiveValueTypeEEClass"); - MockMethodTable pvtMT = rtsBuilder.AddMethodTable("PrimitiveValueType"); - pvtMT.MTFlags = (uint)MethodTableFlags_1.WFLAGS_HIGH.Category_PrimitiveValueType; - pvtMT.BaseSize = rtsBuilder.Builder.TargetTestHelpers.ObjectBaseSize; - pvtMT.ParentMethodTable = systemObjectMethodTablePtr; - pvtMT.NumVirtuals = 3; - pvtEEClass.MethodTable = pvtMT.Address; - pvtMT.EEClassOrCanonMT = pvtEEClass.Address; - primitiveValueTypeMTPtr = pvtMT.Address; + MockEEClass enumEEClass = rtsBuilder.AddEEClass("EnumEEClass"); + MockMethodTable enumMT = rtsBuilder.AddMethodTable("Enum"); + enumMT.MTFlags = (uint)MethodTableFlags_1.WFLAGS_HIGH.Category_Enum; + enumMT.BaseSize = rtsBuilder.Builder.TargetTestHelpers.ObjectBaseSize; + enumMT.ParentMethodTable = systemObjectMethodTablePtr; + enumMT.NumVirtuals = 3; + enumEEClass.MethodTable = enumMT.Address; + enumMT.EEClassOrCanonMT = enumEEClass.Address; + enumMTPtr = enumMT.Address; MockEEClass tpEEClass = rtsBuilder.AddEEClass("TruePrimitiveEEClass"); MockMethodTable tpMT = rtsBuilder.AddMethodTable("TruePrimitive"); @@ -625,7 +625,7 @@ public void IsValueTypeReturnsTrueForValueTypeCategories(MockTarget.Architecture Assert.True(contract.IsValueType(contract.GetTypeHandle(valueTypeMTPtr))); Assert.True(contract.IsValueType(contract.GetTypeHandle(nullableMTPtr))); - Assert.True(contract.IsValueType(contract.GetTypeHandle(primitiveValueTypeMTPtr))); + Assert.True(contract.IsValueType(contract.GetTypeHandle(enumMTPtr))); Assert.True(contract.IsValueType(contract.GetTypeHandle(truePrimitiveMTPtr))); }