* `IDynamicInterfaceCastableFlag` cannot be set on types that have a component size, so move it from the valuable location in `Flags` to `FlagsEx`.
* Move `HasSealedVTableEntriesFlag` from rare flags to flags. This flag is not so rare. All async state machine types set it, for example.
* Delete `IsAbstractClassFlag`. This was introduce in .NET Native for `GetUninitializedObject` since accessing `Type.IsAbstract` could trigger a `MissingMetadataException` there. We got rid of that concept in NativeAOT because it cannot be reconciled with ILLink trimming. Rewrite the code to use `Type.IsAbstract`.
Saves 15 kB on BasicMinimalApis, which is nice. Also makes things faster since we avoid reading optional fields and rare flags.
}
}
- internal bool IsAbstract
- {
- get
- {
- return IsInterface || (RareFlags & EETypeRareFlags.IsAbstractClassFlag) != 0;
- }
- }
-
internal bool IsByRefLike
{
get
{
get
{
- return ((_uFlags & (uint)EETypeFlags.IDynamicInterfaceCastableFlag) != 0);
+ return ((ExtendedFlags & (ushort)EETypeFlagsEx.IDynamicInterfaceCastableFlag) != 0);
}
}
}
}
+ internal bool HasSealedVTableEntries
+ {
+ get
+ {
+ return (_uFlags & (uint)EETypeFlags.HasSealedVTableEntriesFlag) != 0;
+ }
+ }
+
internal bool ContainsGCPointers
{
get
#endif
void* GetSealedVirtualTable()
{
- Debug.Assert((RareFlags & EETypeRareFlags.HasSealedVTableEntriesFlag) != 0);
+ Debug.Assert(HasSealedVTableEntries);
uint cbSealedVirtualSlotsTypeOffset = GetFieldOffset(EETypeField.ETF_SealedVirtualSlots);
byte* pThis = (byte*)Unsafe.AsPointer(ref this);
if (eField == EETypeField.ETF_SealedVirtualSlots)
return cbOffset;
- EETypeRareFlags rareFlags = RareFlags;
-
// in the case of sealed vtable entries on static types, we have a UInt sized relative pointer
- if ((rareFlags & EETypeRareFlags.HasSealedVTableEntriesFlag) != 0)
+ if (HasSealedVTableEntries)
cbOffset += relativeOrFullPointerOffset;
if (eField == EETypeField.ETF_GenericDefinition)
if (IsDynamicType)
cbOffset += (uint)IntPtr.Size;
+ EETypeRareFlags rareFlags = RareFlags;
if (eField == EETypeField.ETF_DynamicGcStatics)
{
Debug.Assert((rareFlags & EETypeRareFlags.IsDynamicTypeWithGcStatics) != 0);
throw new SerializationException(SR.Format(SR.Serialization_InvalidType, type));
}
- if (type.HasElementType || type.IsGenericParameter)
+ if (type.HasElementType || type.IsGenericParameter || type.IsFunctionPointer)
{
throw new ArgumentException(SR.Argument_InvalidValue);
}
throw new NotSupportedException(SR.NotSupported_ManagedActivation);
}
+ if (type.IsAbstract)
+ {
+ throw new MemberAccessException(SR.Acc_CreateAbst);
+ }
+
MethodTable* mt = type.TypeHandle.ToMethodTable();
if (mt->ElementType == Internal.Runtime.EETypeElementType.Void)
throw new MemberAccessException();
}
- if (mt->IsAbstract)
- {
- throw new MemberAccessException(SR.Acc_CreateAbst);
- }
-
if (mt->IsByRefLike)
{
throw new NotSupportedException(SR.NotSupported_ByRefLike);
bool isNullable;
bool isArray;
bool isGeneric;
+ bool hasSealedVTable;
uint flags;
ushort runtimeInterfacesLength = 0;
IntPtr typeManager = IntPtr.Zero;
flags = pTemplateEEType->Flags;
isArray = pTemplateEEType->IsArray;
isGeneric = pTemplateEEType->IsGeneric;
+ hasSealedVTable = pTemplateEEType->HasSealedVTableEntries;
typeManager = pTemplateEEType->PointerToTypeManager;
Debug.Assert(pTemplateEEType->NumInterfaces == runtimeInterfacesLength);
runtimeInterfacesLength,
hasFinalizer,
cbOptionalFieldsSize > 0,
- (rareFlags & (int)EETypeRareFlags.HasSealedVTableEntriesFlag) != 0,
+ hasSealedVTable,
isGeneric,
numFunctionPointerTypeParameters,
allocatedNonGCDataSize != 0,
}
// Copy the sealed vtable entries if they exist on the template type
- if ((rareFlags & (int)EETypeRareFlags.HasSealedVTableEntriesFlag) != 0)
+ if (hasSealedVTable)
{
uint cbSealedVirtualSlotsTypeOffset = pEEType->GetFieldOffset(EETypeField.ETF_SealedVirtualSlots);
*((void**)((byte*)pEEType + cbSealedVirtualSlotsTypeOffset)) = pTemplateEEType->GetSealedVirtualTable();
flagsEx |= (ushort)EETypeFlagsEx.IsTrackedReferenceWithFinalizerFlag;
}
+ if (type.IsIDynamicInterfaceCastable)
+ {
+ flagsEx |= (ushort)EETypeFlagsEx.IDynamicInterfaceCastableFlag;
+ }
+
return flagsEx;
}
HasPointersFlag = 0x00200000,
/// <summary>
- /// This type implements IDynamicInterfaceCastable to allow dynamic resolution of interface casts.
+ /// This MethodTable has sealed vtable entries
/// </summary>
- IDynamicInterfaceCastableFlag = 0x00400000,
+ HasSealedVTableEntriesFlag = 0x00400000,
/// <summary>
/// This type is generic and one or more of its type parameters is co- or contra-variant. This
HasEagerFinalizerFlag = 0x0001,
HasCriticalFinalizerFlag = 0x0002,
IsTrackedReferenceWithFinalizerFlag = 0x0004,
+
+ /// <summary>
+ /// This type implements IDynamicInterfaceCastable to allow dynamic resolution of interface casts.
+ /// </summary>
+ IDynamicInterfaceCastableFlag = 0x0008,
}
internal enum EETypeKind : uint
/// </summary>
IsHFAFlag = 0x00000100,
- /// <summary>
- /// This MethodTable has sealed vtable entries
- /// </summary>
- HasSealedVTableEntriesFlag = 0x00000200,
+ // Unused = 0x00000200,
/// <summary>
/// This dynamically created types has gc statics
// UNUSED = 0x00002000,
- /// <summary>
- /// This MethodTable is an abstract class (but not an interface).
- /// </summary>
- IsAbstractClassFlag = 0x00004000,
+ // UNUSED = 0x00004000,
/// <summary>
/// This MethodTable is for a Byref-like class (TypedReference, Span<T>,...)
ComputeOptionalEETypeFields(factory, relocsOnly);
OutputGCDesc(ref objData);
- OutputFlags(factory, ref objData);
+ OutputFlags(factory, ref objData, relocsOnly);
objData.EmitInt(BaseSize);
OutputRelatedType(factory, ref objData);
Debug.Assert(GCDescSize == 0);
}
- private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData)
+ private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData, bool relocsOnly)
{
uint flags = EETypeBuilderHelpers.ComputeFlags(_type);
flags |= (uint)EETypeFlags.GenericVarianceFlag;
}
- if (_type.IsIDynamicInterfaceCastable)
+ if (EmitVirtualSlotsAndInterfaces && !_type.IsArrayTypeWithoutGenericInterfaces())
{
- flags |= (uint)EETypeFlags.IDynamicInterfaceCastableFlag;
+ SealedVTableNode sealedVTable = factory.SealedVTable(_type.ConvertToCanonForm(CanonicalFormKind.Specific));
+ if (sealedVTable.BuildSealedVTableSlots(factory, relocsOnly) && sealedVTable.NumSealedVTableEntries > 0)
+ flags |= (uint)EETypeFlags.HasSealedVTableEntriesFlag;
}
if (HasOptionalFields)
_optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.DispatchMap, checked((uint)factory.InterfaceDispatchMapIndirection(canonType).IndexFromBeginningOfArray));
}
- ComputeRareFlags(factory, relocsOnly);
+ ComputeRareFlags(factory);
ComputeNullableValueOffset();
ComputeValueTypeFieldPadding();
}
- private void ComputeRareFlags(NodeFactory factory, bool relocsOnly)
+ private void ComputeRareFlags(NodeFactory factory)
{
uint flags = 0;
flags |= (uint)EETypeRareFlags.IsHFAFlag;
}
- if (metadataType != null && !_type.IsInterface && metadataType.IsAbstract)
- {
- flags |= (uint)EETypeRareFlags.IsAbstractClassFlag;
- }
-
if (_type.IsByRefLike)
{
flags |= (uint)EETypeRareFlags.IsByRefLikeFlag;
}
- if (EmitVirtualSlotsAndInterfaces && !_type.IsArrayTypeWithoutGenericInterfaces())
- {
- SealedVTableNode sealedVTable = factory.SealedVTable(_type.ConvertToCanonForm(CanonicalFormKind.Specific));
- if (sealedVTable.BuildSealedVTableSlots(factory, relocsOnly) && sealedVTable.NumSealedVTableEntries > 0)
- flags |= (uint)EETypeRareFlags.HasSealedVTableEntriesFlag;
- }
-
if (flags != 0)
{
_optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.RareFlags, flags);