diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs
index 2255fde37cf097..f9b419a5d8c124 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs
@@ -161,7 +161,6 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
pTemplateEEType = pTemplateEEType->DynamicTemplateType;
}
- uint valueTypeFieldPaddingEncoded = 0;
int baseSize = 0;
bool isValueType;
@@ -171,8 +170,6 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
bool isGeneric;
uint flags;
ushort runtimeInterfacesLength = 0;
- bool isAbstractClass;
- bool isByRefLike;
IntPtr typeManager = IntPtr.Zero;
if (state.RuntimeInterfaces != null)
@@ -180,10 +177,6 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
runtimeInterfacesLength = checked((ushort)state.RuntimeInterfaces.Length);
}
- valueTypeFieldPaddingEncoded = EETypeBuilderHelpers.ComputeValueTypeFieldPaddingFieldValue(
- pTemplateEEType->ValueTypeFieldPadding,
- (uint)pTemplateEEType->FieldAlignmentRequirement,
- IntPtr.Size);
baseSize = (int)pTemplateEEType->BaseSize;
isValueType = pTemplateEEType->IsValueType;
hasFinalizer = pTemplateEEType->IsFinalizable;
@@ -191,48 +184,18 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
flags = pTemplateEEType->Flags;
isArray = pTemplateEEType->IsArray;
isGeneric = pTemplateEEType->IsGeneric;
- isAbstractClass = pTemplateEEType->IsAbstract && !pTemplateEEType->IsInterface;
- isByRefLike = pTemplateEEType->IsByRefLike;
typeManager = pTemplateEEType->PointerToTypeManager;
Debug.Assert(pTemplateEEType->NumInterfaces == runtimeInterfacesLength);
flags |= (uint)EETypeFlags.IsDynamicTypeFlag;
- // TODO! Change to if template is Universal or non-Existent
-
- // FEATURE_UNIVERSAL_GENERICS?
- if (state.TypeSize.HasValue)
+ if (state.TypeBeingBuilt.IsMdArray)
{
- baseSize = state.TypeSize.Value;
-
- int baseSizeBeforeAlignment = baseSize;
-
- baseSize = MemoryHelpers.AlignUp(baseSize, IntPtr.Size);
-
- if (isValueType)
- {
- // Compute the valuetype padding size based on size before adding the object type pointer field to the size
- uint cbValueTypeFieldPadding = (uint)(baseSize - baseSizeBeforeAlignment);
-
- // Add Object type pointer field to base size
- baseSize += IntPtr.Size;
-
- valueTypeFieldPaddingEncoded = (uint)EETypeBuilderHelpers.ComputeValueTypeFieldPaddingFieldValue(cbValueTypeFieldPadding, (uint)state.FieldAlignment.Value, IntPtr.Size);
- }
-
- // Minimum base size is 3 pointers, and requires us to bump the size of an empty class type
- if (baseSize <= IntPtr.Size)
- {
- // ValueTypes should already have had their size bumped up by the normal type layout process
- Debug.Assert(!isValueType);
- baseSize += IntPtr.Size;
- }
-
- // Add sync block skew
- baseSize += IntPtr.Size;
-
- // Minimum basesize is 3 pointers
- Debug.Assert(baseSize >= (IntPtr.Size * 3));
+ // If we're building an MDArray, the template is object[,] and we
+ // need to recompute the base size.
+ baseSize = IntPtr.Size + // sync block
+ 2 * IntPtr.Size + // EETypePtr + Length
+ state.ArrayRank.Value * sizeof(int) * 2; // 2 ints per rank for bounds
}
// Optional fields encoding
@@ -241,7 +204,11 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
uint rareFlags = optionalFields.GetFieldValue(EETypeOptionalFieldTag.RareFlags, 0);
- if (state.NonGcDataSize != 0)
+ int allocatedNonGCDataSize = state.NonGcDataSize;
+ if (state.HasStaticConstructor)
+ allocatedNonGCDataSize += -TypeBuilder.ClassConstructorOffset;
+
+ if (allocatedNonGCDataSize != 0)
rareFlags |= (uint)EETypeRareFlags.IsDynamicTypeWithNonGcStatics;
if (state.GcDataSize != 0)
@@ -250,60 +217,11 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
if (state.ThreadDataSize != 0)
rareFlags |= (uint)EETypeRareFlags.IsDynamicTypeWithThreadStatics;
-#if TARGET_ARM
- if (state.FieldAlignment == 8)
- rareFlags |= (uint)EETypeRareFlags.RequiresAlign8Flag;
- else
- rareFlags &= ~(uint)EETypeRareFlags.RequiresAlign8Flag;
-#endif
-
-#if TARGET_ARM || TARGET_ARM64
- if (state.IsHFA)
- rareFlags |= (uint)EETypeRareFlags.IsHFAFlag;
- else
- rareFlags &= ~(uint)EETypeRareFlags.IsHFAFlag;
-#endif
- if (state.HasStaticConstructor)
- rareFlags |= (uint)EETypeRareFlags.HasCctorFlag;
- else
- rareFlags &= ~(uint)EETypeRareFlags.HasCctorFlag;
-
- if (isAbstractClass)
- rareFlags |= (uint)EETypeRareFlags.IsAbstractClassFlag;
- else
- rareFlags &= ~(uint)EETypeRareFlags.IsAbstractClassFlag;
-
- if (isByRefLike)
- rareFlags |= (uint)EETypeRareFlags.IsByRefLikeFlag;
- else
- rareFlags &= ~(uint)EETypeRareFlags.IsByRefLikeFlag;
-
- if (isNullable)
- {
- uint nullableValueOffset = state.NullableValueOffset;
-
- // The stored offset is never zero (Nullable has a boolean there indicating whether the value is valid).
- // If the real offset is one, then the field isn't set. Otherwise the offset is encoded - 1 to save space.
- if (nullableValueOffset == 1)
- optionalFields.ClearField(EETypeOptionalFieldTag.NullableValueOffset);
- else
- optionalFields.SetFieldValue(EETypeOptionalFieldTag.NullableValueOffset, checked(nullableValueOffset - 1));
- }
- else
- {
- optionalFields.ClearField(EETypeOptionalFieldTag.NullableValueOffset);
- }
-
optionalFields.SetFieldValue(EETypeOptionalFieldTag.RareFlags, rareFlags);
// Dispatch map is fetched from template type
optionalFields.ClearField(EETypeOptionalFieldTag.DispatchMap);
- optionalFields.ClearField(EETypeOptionalFieldTag.ValueTypeFieldPadding);
-
- if (valueTypeFieldPaddingEncoded != 0)
- optionalFields.SetFieldValue(EETypeOptionalFieldTag.ValueTypeFieldPadding, valueTypeFieldPaddingEncoded);
-
// Compute size of optional fields encoding
cbOptionalFieldsSize = optionalFields.Encode();
Debug.Assert(cbOptionalFieldsSize > 0);
@@ -328,7 +246,7 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
true,
(rareFlags & (int)EETypeRareFlags.HasSealedVTableEntriesFlag) != 0,
isGeneric,
- state.NonGcDataSize != 0,
+ allocatedNonGCDataSize != 0,
state.GcDataSize != 0,
state.ThreadDataSize != 0);
@@ -401,7 +319,7 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
nonGCStaticDataOffset = state.HasStaticConstructor ? -TypeBuilder.ClassConstructorOffset : 0;
// If we have a class constructor, our NonGcDataSize MUST be non-zero
- Debug.Assert(!state.HasStaticConstructor || (state.NonGcDataSize != 0));
+ Debug.Assert(!state.HasStaticConstructor || (allocatedNonGCDataSize != 0));
}
if (isGeneric)
@@ -409,11 +327,11 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo
genericComposition = MemoryHelpers.AllocateMemory(MethodTable.GetGenericCompositionSize(arity, pEEType->HasGenericVariance));
pEEType->SetGenericComposition(genericComposition);
- if (state.NonGcDataSize > 0)
+ if (allocatedNonGCDataSize > 0)
{
- nonGcStaticData = MemoryHelpers.AllocateMemory(state.NonGcDataSize);
- MemoryHelpers.Memset(nonGcStaticData, state.NonGcDataSize, 0);
- Debug.Assert(nonGCStaticDataOffset <= state.NonGcDataSize);
+ nonGcStaticData = MemoryHelpers.AllocateMemory(allocatedNonGCDataSize);
+ MemoryHelpers.Memset(nonGcStaticData, allocatedNonGCDataSize, 0);
+ Debug.Assert(nonGCStaticDataOffset <= allocatedNonGCDataSize);
pEEType->DynamicNonGcStaticsData = (IntPtr)((byte*)nonGcStaticData + nonGCStaticDataOffset);
}
}
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs
deleted file mode 100644
index f619b47d513196..00000000000000
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using Internal.TypeSystem;
-using System.Diagnostics;
-using Internal.NativeFormat;
-using System.Collections.Generic;
-using Internal.Runtime.Augments;
-
-namespace Internal.Runtime.TypeLoader
-{
- ///
- /// Reads field layout based on native layout data
- /// information
- ///
- internal class NativeLayoutFieldAlgorithm : FieldLayoutAlgorithm
- {
- private NoMetadataFieldLayoutAlgorithm _noMetadataFieldLayoutAlgorithm = new NoMetadataFieldLayoutAlgorithm();
- private const int InstanceAlignmentEntry = 4;
-
- public override unsafe bool ComputeContainsGCPointers(DefType type)
- {
- Debug.Assert(type.IsTemplateCanonical());
- return type.ComputeTemplate().RuntimeTypeHandle.ToEETypePtr()->HasGCPointers;
- }
-
- public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
- {
- Debug.Assert(!type.IsTemplateUniversal() && (layoutKind == InstanceLayoutKind.TypeOnly));
- DefType template = (DefType)type.ComputeTemplate();
- return _noMetadataFieldLayoutAlgorithm.ComputeInstanceLayout(template, InstanceLayoutKind.TypeOnly);
- }
-
- public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType type, StaticLayoutKind layoutKind)
- {
- Debug.Assert(!type.IsTemplateUniversal() && (layoutKind == StaticLayoutKind.StaticRegionSizes));
- return ParseStaticRegionSizesFromNativeLayout(type);
- }
-
- private static ComputedStaticFieldLayout ParseStaticRegionSizesFromNativeLayout(TypeDesc type)
- {
- LayoutInt nonGcDataSize = LayoutInt.Zero;
- LayoutInt gcDataSize = LayoutInt.Zero;
- LayoutInt threadDataSize = LayoutInt.Zero;
-
- TypeBuilderState state = type.GetOrCreateTypeBuilderState();
- NativeParser typeInfoParser = state.GetParserForNativeLayoutInfo();
-
- BagElementKind kind;
- while ((kind = typeInfoParser.GetBagElementKind()) != BagElementKind.End)
- {
- switch (kind)
- {
- case BagElementKind.NonGcStaticDataSize:
- TypeLoaderLogger.WriteLine("Found BagElementKind.NonGcStaticDataSize");
- // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
- nonGcDataSize = new LayoutInt(checked((int)typeInfoParser.GetUnsigned()));
- break;
-
- case BagElementKind.GcStaticDataSize:
- TypeLoaderLogger.WriteLine("Found BagElementKind.GcStaticDataSize");
- // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
- gcDataSize = new LayoutInt(checked((int)typeInfoParser.GetUnsigned()));
- break;
-
- case BagElementKind.ThreadStaticDataSize:
- TypeLoaderLogger.WriteLine("Found BagElementKind.ThreadStaticDataSize");
- // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
- threadDataSize = new LayoutInt(checked((int)typeInfoParser.GetUnsigned()));
- break;
-
- default:
- typeInfoParser.SkipInteger();
- break;
- }
- }
-
- ComputedStaticFieldLayout staticLayout = new ComputedStaticFieldLayout()
- {
- GcStatics = new StaticsBlock() { Size = gcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible },
- NonGcStatics = new StaticsBlock() { Size = nonGcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible },
- Offsets = null, // We're not computing field offsets here, so return null
- ThreadGcStatics = new StaticsBlock() { Size = threadDataSize, LargestAlignment = DefType.MaximumAlignmentPossible },
- ThreadNonGcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero },
- };
-
- return staticLayout;
- }
-
- public override unsafe ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type)
- {
- // Use this constant to make the code below more laconic
- const ValueTypeShapeCharacteristics NotHA = ValueTypeShapeCharacteristics.None;
-
- Debug.Assert(type.IsValueType);
-
- TargetArchitecture targetArch = type.Context.Target.Architecture;
- if ((targetArch != TargetArchitecture.ARM) && (targetArch != TargetArchitecture.ARM64))
- return NotHA;
-
- if (!type.IsValueType)
- return NotHA;
-
- // There is no reason to compute the entire field layout for the HA type/flag if
- // the template type is not a universal generic type (information stored in rare flags on the MethodTable)
- TypeDesc templateType = type.ComputeTemplate(false);
- Debug.Assert(templateType != null && !templateType.IsCanonicalSubtype(CanonicalFormKind.Universal));
- MethodTable* pEETemplate = templateType.GetRuntimeTypeHandle().ToEETypePtr();
- if (!pEETemplate->IsHFA)
- return NotHA;
-
- if (pEETemplate->RequiresAlign8)
- return ValueTypeShapeCharacteristics.Float64Aggregate;
- else
- return ValueTypeShapeCharacteristics.Float32Aggregate;
- }
-
- public override bool ComputeIsUnsafeValueType(DefType type)
- {
- throw new NotSupportedException();
- }
- }
-}
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs
deleted file mode 100644
index 38124252019de0..00000000000000
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using Internal.TypeSystem;
-using System.Diagnostics;
-
-namespace Internal.Runtime.TypeLoader
-{
- ///
- /// Useable when we have runtime MethodTable structures. Can represent the field layout necessary
- /// to represent the size/alignment of the overall type, but must delegate to either NativeLayoutFieldAlgorithm
- /// or MetadataFieldLayoutAlgorithm to get information about individual fields.
- ///
- internal class NoMetadataFieldLayoutAlgorithm : FieldLayoutAlgorithm
- {
- private static NativeLayoutFieldAlgorithm s_nativeLayoutFieldAlgorithm = new NativeLayoutFieldAlgorithm();
-
- public override unsafe bool ComputeContainsGCPointers(DefType type)
- {
- return type.RuntimeTypeHandle.ToEETypePtr()->HasGCPointers;
- }
-
- ///
- /// Reads the minimal information about type layout encoded in the
- /// MethodTable. That doesn't include field information.
- ///
- public override unsafe ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
- {
- // If we need the field information, delegate to the native layout algorithm or metadata algorithm
- if (layoutKind != InstanceLayoutKind.TypeOnly)
- {
- Debug.Assert(type.HasNativeLayout);
- return s_nativeLayoutFieldAlgorithm.ComputeInstanceLayout(type, layoutKind);
- }
-
- type.RetrieveRuntimeTypeHandleIfPossible();
- Debug.Assert(!type.RuntimeTypeHandle.IsNull());
- MethodTable* MethodTable = type.RuntimeTypeHandle.ToEETypePtr();
-
- ComputedInstanceFieldLayout layout = new ComputedInstanceFieldLayout()
- {
- ByteCountAlignment = new LayoutInt(IntPtr.Size),
- ByteCountUnaligned = new LayoutInt(MethodTable->IsInterface ? IntPtr.Size : checked((int)MethodTable->FieldByteCountNonGCAligned)),
- FieldAlignment = new LayoutInt(MethodTable->FieldAlignmentRequirement),
- Offsets = (layoutKind == InstanceLayoutKind.TypeOnly) ? null : Array.Empty(), // No fields in EETypes
- };
-
- if (MethodTable->IsValueType)
- {
- int valueTypeSize = checked((int)MethodTable->ValueTypeSize);
- layout.FieldSize = new LayoutInt(valueTypeSize);
- }
- else
- {
- layout.FieldSize = new LayoutInt(IntPtr.Size);
- }
-
- if ((MethodTable->RareFlags & EETypeRareFlags.RequiresAlign8Flag) == EETypeRareFlags.RequiresAlign8Flag)
- {
- layout.ByteCountAlignment = new LayoutInt(8);
- }
-
- return layout;
- }
-
- public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType type, StaticLayoutKind layoutKind)
- {
- Debug.Assert(false);
- return default;
- }
-
- public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type)
- {
- if (type.Context.Target.Architecture == TargetArchitecture.ARM)
- {
- unsafe
- {
- // On ARM, the HFA type is encoded into the MethodTable directly
- type.RetrieveRuntimeTypeHandleIfPossible();
- Debug.Assert(!type.RuntimeTypeHandle.IsNull());
- MethodTable* MethodTable = type.RuntimeTypeHandle.ToEETypePtr();
-
- if (!MethodTable->IsHFA)
- return ValueTypeShapeCharacteristics.None;
-
- if (MethodTable->RequiresAlign8)
- return ValueTypeShapeCharacteristics.Float64Aggregate;
- else
- return ValueTypeShapeCharacteristics.Float32Aggregate;
- }
- }
- else
- {
- Debug.Assert(
- type.Context.Target.Architecture == TargetArchitecture.X86 ||
- type.Context.Target.Architecture == TargetArchitecture.X64);
-
- return ValueTypeShapeCharacteristics.None;
- }
- }
-
- public override bool ComputeIsUnsafeValueType(DefType type)
- {
- throw new NotSupportedException();
- }
- }
-}
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs
index 4d0da15912ae49..65c981592a1cda 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs
@@ -260,9 +260,6 @@ internal void PrepareType(TypeDesc type)
{
Debug.Assert(typeAsArrayType.IsMdArray || typeAsArrayType.ElementType.IsPointer);
}
-
- // Assert that non-valuetypes are considered to have pointer size
- Debug.Assert(typeAsArrayType.ParameterType.IsValueType || state.ComponentSize == IntPtr.Size);
}
}
else
@@ -276,11 +273,7 @@ internal void PrepareType(TypeDesc type)
PrepareBaseTypeAndDictionaries(type);
PrepareRuntimeInterfaces(type);
- TypeLoaderLogger.WriteLine("Layout for type " + type.ToString() + " complete." +
- " IsHFA = " + (state.IsHFA ? "true" : "false") +
- " Type size = " + (state.TypeSize.HasValue ? state.TypeSize.Value.LowLevelToString() : "UNDEF") +
- " Fields size = " + (state.UnalignedTypeSize.HasValue ? state.UnalignedTypeSize.Value.LowLevelToString() : "UNDEF") +
- " Type alignment = " + (state.FieldAlignment.HasValue ? state.FieldAlignment.Value.LowLevelToString() : "UNDEF"));
+ TypeLoaderLogger.WriteLine("Layout for type " + type.ToString() + " complete.");
}
}
@@ -400,13 +393,6 @@ internal void ParseNativeLayoutInfo(TypeBuilderState state, TypeDesc type)
NativeParser baseTypeParser = new NativeParser();
- int nonGcDataSize = 0;
- int gcDataSize = 0;
- int threadDataSize = 0;
- bool staticSizesMeaningful = (type is DefType) // Is type permitted to have static fields
- && !isTemplateUniversalCanon; // Non-universal templates always specify their statics sizes
- // if the size can be greater than 0
-
BagElementKind kind;
while ((kind = typeInfoParser.GetBagElementKind()) != BagElementKind.End)
{
@@ -432,22 +418,19 @@ internal void ParseNativeLayoutInfo(TypeBuilderState state, TypeDesc type)
case BagElementKind.NonGcStaticDataSize:
TypeLoaderLogger.WriteLine("Found BagElementKind.NonGcStaticDataSize");
// Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
- nonGcDataSize = checked((int)typeInfoParser.GetUnsigned());
- Debug.Assert(staticSizesMeaningful);
+ state.NonGcDataSize = checked((int)typeInfoParser.GetUnsigned());
break;
case BagElementKind.GcStaticDataSize:
TypeLoaderLogger.WriteLine("Found BagElementKind.GcStaticDataSize");
// Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
- gcDataSize = checked((int)typeInfoParser.GetUnsigned());
- Debug.Assert(staticSizesMeaningful);
+ state.GcDataSize = checked((int)typeInfoParser.GetUnsigned());
break;
case BagElementKind.ThreadStaticDataSize:
TypeLoaderLogger.WriteLine("Found BagElementKind.ThreadStaticDataSize");
// Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
- threadDataSize = checked((int)typeInfoParser.GetUnsigned());
- Debug.Assert(staticSizesMeaningful);
+ state.ThreadDataSize = checked((int)typeInfoParser.GetUnsigned());
break;
case BagElementKind.GcStaticDesc:
@@ -493,13 +476,6 @@ internal void ParseNativeLayoutInfo(TypeBuilderState state, TypeDesc type)
}
}
- if (staticSizesMeaningful)
- {
- Debug.Assert((state.NonGcDataSize + (state.HasStaticConstructor ? TypeBuilder.ClassConstructorOffset : 0)) == nonGcDataSize);
- Debug.Assert(state.GcDataSize == gcDataSize);
- Debug.Assert(state.ThreadDataSize == threadDataSize);
- }
-
type.ParseBaseType(context, baseTypeParser);
}
@@ -847,9 +823,16 @@ private void FinishRuntimeType(TypeDesc type)
{
if (type is ArrayType typeAsSzArrayType)
{
- state.HalfBakedRuntimeTypeHandle.SetRelatedParameterType(GetRuntimeTypeHandle(typeAsSzArrayType.ElementType));
+ RuntimeTypeHandle elementTypeHandle = GetRuntimeTypeHandle(typeAsSzArrayType.ElementType);
+ state.HalfBakedRuntimeTypeHandle.SetRelatedParameterType(elementTypeHandle);
- state.HalfBakedRuntimeTypeHandle.SetComponentSize(state.ComponentSize.Value);
+ ushort componentSize = (ushort)IntPtr.Size;
+ unsafe
+ {
+ if (typeAsSzArrayType.ElementType.IsValueType)
+ componentSize = checked((ushort)elementTypeHandle.ToEETypePtr()->ValueTypeSize);
+ }
+ state.HalfBakedRuntimeTypeHandle.SetComponentSize(componentSize);
FinishInterfaces(state);
}
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs
index 8305f1e492916c..7cf922fd75f4d7 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs
@@ -280,59 +280,9 @@ public ushort NumVTableSlots
public GenericTypeDictionary Dictionary;
- public int NonGcDataSize
- {
- get
- {
- DefType defType = TypeBeingBuilt as DefType;
-
- // The NonGCStatic fields hold the class constructor data if it exists in the negative space
- // of the memory region. The ClassConstructorOffset is negative, so it must be negated to
- // determine the extra space that is used.
-
- if (defType != null)
- {
- return defType.NonGCStaticFieldSize.AsInt - (HasStaticConstructor ? TypeBuilder.ClassConstructorOffset : 0);
- }
- else
- {
- return -(HasStaticConstructor ? TypeBuilder.ClassConstructorOffset : 0);
- }
- }
- }
-
- public int GcDataSize
- {
- get
- {
- DefType defType = TypeBeingBuilt as DefType;
- if (defType != null)
- {
- return defType.GCStaticFieldSize.AsInt;
- }
- else
- {
- return 0;
- }
- }
- }
-
- public int ThreadDataSize
- {
- get
- {
- DefType defType = TypeBeingBuilt as DefType;
- if (defType != null && !defType.IsGenericDefinition)
- {
- return defType.ThreadGcStaticFieldSize.AsInt;
- }
- else
- {
- // Non-DefType's and GenericEETypeDefinitions do not have static fields of any form
- return 0;
- }
- }
- }
+ public int NonGcDataSize;
+ public int GcDataSize;
+ public int ThreadDataSize;
public bool HasStaticConstructor
{
@@ -522,180 +472,5 @@ public int? ArrayRank
}
}
}
-
- public int? BaseTypeSize
- {
- get
- {
- if (TypeBeingBuilt.BaseType == null)
- {
- return null;
- }
- else
- {
- return TypeBeingBuilt.BaseType.InstanceByteCountUnaligned.AsInt;
- }
- }
- }
-
- public int? TypeSize
- {
- get
- {
- DefType defType = TypeBeingBuilt as DefType;
- if (defType != null)
- {
- // Generic Type Definition EETypes do not have size
- if (defType.IsGenericDefinition)
- return null;
-
- if (defType.IsValueType)
- {
- return defType.InstanceFieldSize.AsInt;
- }
- else
- {
- if (defType.IsInterface)
- return IntPtr.Size;
-
- return defType.InstanceByteCountUnaligned.AsInt;
- }
- }
- else if (TypeBeingBuilt is ArrayType)
- {
- int basicArraySize = 2 * IntPtr.Size; // EETypePtr + Length
- if (TypeBeingBuilt.IsMdArray)
- {
- // MD Arrays are arranged like normal arrays, but they also have 2 int's per rank for the individual dimension loBounds and range.
- basicArraySize += ((ArrayType)TypeBeingBuilt).Rank * sizeof(int) * 2;
- }
- return basicArraySize;
- }
- else
- {
- return null;
- }
- }
- }
-
- public int? UnalignedTypeSize
- {
- get
- {
- DefType defType = TypeBeingBuilt as DefType;
- if (defType != null)
- {
- return defType.InstanceByteCountUnaligned.AsInt;
- }
- else if (TypeBeingBuilt is ArrayType)
- {
- // Arrays use the same algorithm for TypeSize as for UnalignedTypeSize
- return TypeSize;
- }
- else
- {
- return 0;
- }
- }
- }
-
- public int? FieldAlignment
- {
- get
- {
- if (TypeBeingBuilt is DefType)
- {
- return checked((ushort)((DefType)TypeBeingBuilt).InstanceFieldAlignment.AsInt);
- }
- else if (TypeBeingBuilt is ArrayType arrayType)
- {
- if (arrayType.ElementType is DefType)
- {
- return checked((ushort)((DefType)arrayType.ElementType).InstanceFieldAlignment.AsInt);
- }
- else
- {
- return (ushort)arrayType.Context.Target.PointerSize;
- }
- }
- else if (TypeBeingBuilt is PointerType || TypeBeingBuilt is ByRefType)
- {
- return (ushort)TypeBeingBuilt.Context.Target.PointerSize;
- }
- else
- {
- return null;
- }
- }
- }
-
- public ushort? ComponentSize
- {
- get
- {
- ArrayType arrayType = TypeBeingBuilt as ArrayType;
- if (arrayType != null)
- {
- if (arrayType.ElementType is DefType)
- {
- uint size = (uint)((DefType)arrayType.ElementType).InstanceFieldSize.AsInt;
-
- if (size > ArrayTypesConstants.MaxSizeForValueClassInArray && arrayType.ElementType.IsValueType)
- ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadValueClassTooLarge, arrayType.ElementType);
-
- return checked((ushort)size);
- }
- else
- {
- return (ushort)arrayType.Context.Target.PointerSize;
- }
- }
- else
- {
- return null;
- }
- }
- }
-
- public uint NullableValueOffset
- {
- get
- {
- if (!TypeBeingBuilt.IsNullable)
- return 0;
-
- Debug.Assert(TypeBeingBuilt.IsTemplateCanonical());
- // Pull the GC Desc from the canonical instantiation
- TypeDesc templateType = TypeBeingBuilt.ComputeTemplate();
- bool success = templateType.RetrieveRuntimeTypeHandleIfPossible();
- Debug.Assert(success);
- unsafe
- {
- return templateType.RuntimeTypeHandle.ToEETypePtr()->NullableValueOffset;
- }
- }
- }
-
-#pragma warning disable CA1822
- public bool IsHFA
- {
- get
- {
-#if TARGET_ARM
- if (TypeBeingBuilt.IsValueType && TypeBeingBuilt is DefType)
- {
- return ((DefType)TypeBeingBuilt).IsHomogeneousAggregate;
- }
- else
- {
- return false;
- }
-#else
- // On Non-ARM platforms, HFA'ness is not encoded in the MethodTable as it doesn't effect ABI
- return false;
-#endif
- }
- }
-#pragma warning restore CA1822
}
}
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderTypeSystemContext.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderTypeSystemContext.cs
index 7dd6bbc01a326c..c6120c5f80a570 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderTypeSystemContext.cs
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderTypeSystemContext.cs
@@ -14,30 +14,13 @@ namespace Internal.Runtime.TypeLoader
///
public partial class TypeLoaderTypeSystemContext : TypeSystemContext
{
- private static readonly NoMetadataFieldLayoutAlgorithm s_noMetadataFieldLayoutAlgorithm = new NoMetadataFieldLayoutAlgorithm();
private static readonly NoMetadataRuntimeInterfacesAlgorithm s_noMetadataRuntimeInterfacesAlgorithm = new NoMetadataRuntimeInterfacesAlgorithm();
- private static readonly NativeLayoutFieldAlgorithm s_nativeLayoutFieldAlgorithm = new NativeLayoutFieldAlgorithm();
private static readonly NativeLayoutInterfacesAlgorithm s_nativeLayoutInterfacesAlgorithm = new NativeLayoutInterfacesAlgorithm();
public TypeLoaderTypeSystemContext(TargetDetails targetDetails) : base(targetDetails)
{
}
- public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type)
- {
- if (type.RetrieveRuntimeTypeHandleIfPossible())
- {
- // If the type is already constructed, use the NoMetadataFieldLayoutAlgorithm.
- // its more efficient than loading from native layout or metadata.
- return s_noMetadataFieldLayoutAlgorithm;
- }
- if (type.HasNativeLayout)
- {
- return s_nativeLayoutFieldAlgorithm;
- }
- return s_noMetadataFieldLayoutAlgorithm;
- }
-
protected override RuntimeInterfacesAlgorithm GetRuntimeInterfacesAlgorithmForDefType(DefType type)
{
if (type.RetrieveRuntimeTypeHandleIfPossible())
diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
index b658cc35b155cc..478156e0371dc3 100644
--- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
+++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
@@ -281,10 +281,8 @@
-
-
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs
index 04a5b32c9acbc5..132b4ba679269d 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs
@@ -1134,11 +1134,8 @@ private void ComputeNullableValueOffset()
protected virtual void ComputeValueTypeFieldPadding()
{
- // All objects that can have appreciable which can be derived from size compute ValueTypeFieldPadding.
- // Unfortunately, the name ValueTypeFieldPadding is now wrong to avoid integration conflicts.
-
- // Interfaces, sealed types, and non-DefTypes cannot be derived from
- if (_type.IsInterface || !_type.IsDefType || (_type.IsSealed() && !_type.IsValueType))
+ // Only valuetypes need to compute the padding.
+ if (!_type.IsValueType)
return;
DefType defType = _type as DefType;
@@ -1154,22 +1151,18 @@ protected virtual void ComputeValueTypeFieldPadding()
{
int numInstanceFieldBytes = defType.InstanceByteCountUnaligned.AsInt;
- // Check if we have a type derived from System.ValueType or System.Enum, but not System.Enum itself
- if (defType.IsValueType)
- {
- // Value types should have at least 1 byte of size
- Debug.Assert(numInstanceFieldBytes >= 1);
+ // Value types should have at least 1 byte of size
+ Debug.Assert(numInstanceFieldBytes >= 1);
- // The size doesn't currently include the MethodTable pointer size. We need to add this so that
- // the number of instance field bytes consistently represents the boxed size.
- numInstanceFieldBytes += _type.Context.Target.PointerSize;
- }
+ // The size of value types doesn't include the MethodTable pointer. We need to add this so that
+ // the number of instance field bytes consistently represents the boxed size.
+ numInstanceFieldBytes += _type.Context.Target.PointerSize;
// For unboxing to work correctly and for supporting dynamic type loading for derived types we need
// to record the actual size of the fields of a type without any padding for GC heap allocation (since
// we can unbox into locals or arrays where this padding is not used, and because field layout for derived
// types is effected by the unaligned base size). We don't want to store this information for all EETypes
- // since it's only relevant for value types, and derivable types so it's added as an optional field. It's
+ // since it's only relevant for value types, so it's added as an optional field. It's
// also enough to simply store the size of the padding (between 0 and 4 or 8 bytes for 32-bit and 0 and 8 or 16 bytes
// for 64-bit) which cuts down our storage requirements.