Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shuffle some MethodTable flags #85634

Merged
merged 2 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 12 additions & 13 deletions src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -639,14 +639,6 @@ internal bool IsInterface
}
}

internal bool IsAbstract
{
get
{
return IsInterface || (RareFlags & EETypeRareFlags.IsAbstractClassFlag) != 0;
}
}

internal bool IsByRefLike
{
get
Expand Down Expand Up @@ -773,7 +765,7 @@ internal bool IsIDynamicInterfaceCastable
{
get
{
return ((_uFlags & (uint)EETypeFlags.IDynamicInterfaceCastableFlag) != 0);
return ((ExtendedFlags & (ushort)EETypeFlagsEx.IDynamicInterfaceCastableFlag) != 0);
}
}

Expand All @@ -794,6 +786,14 @@ internal bool IsPrimitive
}
}

internal bool HasSealedVTableEntries
{
get
{
return (_uFlags & (uint)EETypeFlags.HasSealedVTableEntriesFlag) != 0;
}
}

internal bool ContainsGCPointers
{
get
Expand Down Expand Up @@ -1064,7 +1064,7 @@ private static IntPtr FollowRelativePointer(int* pDist)
#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);
Expand Down Expand Up @@ -1387,10 +1387,8 @@ public uint GetFieldOffset(EETypeField eField)
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)
Expand Down Expand Up @@ -1431,6 +1429,7 @@ public uint GetFieldOffset(EETypeField eField)
if (IsDynamicType)
cbOffset += (uint)IntPtr.Size;

EETypeRareFlags rareFlags = RareFlags;
if (eField == EETypeField.ETF_DynamicGcStatics)
{
Debug.Assert((rareFlags & EETypeRareFlags.IsDynamicTypeWithGcStatics) != 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ public static unsafe object GetUninitializedObject(
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);
}
Expand All @@ -319,6 +319,11 @@ public static unsafe object GetUninitializedObject(
throw new NotSupportedException(SR.NotSupported_ManagedActivation);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Unrelated to this PR)

We are missing a check for function pointers here. Could you please fix it in a follow up?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Activator.CreateInstance seems to be missing it too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not close to a computer now but I think Activator should be fine because there's no constructor to run and they're not a valuetype. I don't see it handling pointers either.


if (type.IsAbstract)
{
throw new MemberAccessException(SR.Acc_CreateAbst);
}

MethodTable* mt = type.TypeHandle.ToMethodTable();

if (mt->ElementType == Internal.Runtime.EETypeElementType.Void)
Expand All @@ -337,11 +342,6 @@ public static unsafe object GetUninitializedObject(
throw new MemberAccessException();
}

if (mt->IsAbstract)
{
throw new MemberAccessException(SR.Acc_CreateAbst);
}

if (mt->IsByRefLike)
{
throw new NotSupportedException(SR.NotSupported_ByRefLike);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
bool isNullable;
bool isArray;
bool isGeneric;
bool hasSealedVTable;
uint flags;
ushort runtimeInterfacesLength = 0;
IntPtr typeManager = IntPtr.Zero;
Expand All @@ -184,6 +185,7 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
flags = pTemplateEEType->Flags;
isArray = pTemplateEEType->IsArray;
isGeneric = pTemplateEEType->IsGeneric;
hasSealedVTable = pTemplateEEType->HasSealedVTableEntries;
typeManager = pTemplateEEType->PointerToTypeManager;
Debug.Assert(pTemplateEEType->NumInterfaces == runtimeInterfacesLength);

Expand Down Expand Up @@ -260,7 +262,7 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
runtimeInterfacesLength,
hasFinalizer,
cbOptionalFieldsSize > 0,
(rareFlags & (int)EETypeRareFlags.HasSealedVTableEntriesFlag) != 0,
hasSealedVTable,
isGeneric,
numFunctionPointerTypeParameters,
allocatedNonGCDataSize != 0,
Expand Down Expand Up @@ -315,7 +317,7 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
}

// 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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ mdType.Name is "WeakReference" or "WeakReference`1" &&
flagsEx |= (ushort)EETypeFlagsEx.IsTrackedReferenceWithFinalizerFlag;
}

if (type.IsIDynamicInterfaceCastable)
{
flagsEx |= (ushort)EETypeFlagsEx.IDynamicInterfaceCastableFlag;
}

return flagsEx;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ internal enum EETypeFlags : uint
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
Expand Down Expand Up @@ -81,6 +81,11 @@ internal enum EETypeFlagsEx : ushort
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
Expand Down Expand Up @@ -140,10 +145,7 @@ internal enum EETypeRareFlags : int
/// </summary>
IsHFAFlag = 0x00000100,

/// <summary>
/// This MethodTable has sealed vtable entries
/// </summary>
HasSealedVTableEntriesFlag = 0x00000200,
// Unused = 0x00000200,

/// <summary>
/// This dynamically created types has gc statics
Expand All @@ -162,10 +164,7 @@ internal enum EETypeRareFlags : int

// 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&lt;T&gt;,...)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo
ComputeOptionalEETypeFields(factory, relocsOnly);

OutputGCDesc(ref objData);
OutputFlags(factory, ref objData);
OutputFlags(factory, ref objData, relocsOnly);
objData.EmitInt(BaseSize);
OutputRelatedType(factory, ref objData);

Expand Down Expand Up @@ -715,7 +715,7 @@ protected virtual void OutputGCDesc(ref ObjectDataBuilder builder)
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);

Expand All @@ -733,9 +733,11 @@ private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData)
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)
Expand Down Expand Up @@ -1189,12 +1191,12 @@ protected internal virtual void ComputeOptionalEETypeFields(NodeFactory factory,
_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;

Expand All @@ -1219,23 +1221,11 @@ private void ComputeRareFlags(NodeFactory factory, bool relocsOnly)
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);
Expand Down