From 5a143e98f313f93b3dda6c299e4abf1e5eb506a3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 22 Oct 2024 19:22:14 +0800 Subject: [PATCH 1/7] Replace with bool[] in GC layout --- .../Runtime/TypeLoader/EETypeCreator.cs | 18 ++++---- .../Runtime/TypeLoader/TypeBuilder.cs | 44 +++++++------------ .../Runtime/TypeLoader/TypeBuilderState.cs | 14 +++--- 3 files changed, 31 insertions(+), 45 deletions(-) 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 9a5995e17fb9ef..a4474f8d7f4b07 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 @@ -457,9 +457,9 @@ private static unsafe int GetInstanceGCDescSize(TypeBuilderState state, MethodTa } } - private static bool IsAllGCPointers(LowLevelList bitfield) + private static bool IsAllGCPointers(bool[] bitfield) { - int count = bitfield.Count; + int count = bitfield.Length; Debug.Assert(count > 0); for (int i = 0; i < count; i++) @@ -471,7 +471,7 @@ private static bool IsAllGCPointers(LowLevelList bitfield) return true; } - private static unsafe int CreateArrayGCDesc(LowLevelList bitfield, int rank, bool isSzArray, void* gcdesc) + private static unsafe int CreateArrayGCDesc(bool[] bitfield, int rank, bool isSzArray, void* gcdesc) { if (bitfield == null) return 0; @@ -495,7 +495,7 @@ private static unsafe int CreateArrayGCDesc(LowLevelList bitfield, int ran int first = -1; int last = 0; short numPtrs = 0; - while (i < bitfield.Count) + while (i < bitfield.Length) { if (bitfield[i]) { @@ -513,7 +513,7 @@ private static unsafe int CreateArrayGCDesc(LowLevelList bitfield, int ran numSeries++; numPtrs = 0; - while ((i < bitfield.Count) && (bitfield[i])) + while ((i < bitfield.Length) && (bitfield[i])) { numPtrs++; i++; @@ -531,7 +531,7 @@ private static unsafe int CreateArrayGCDesc(LowLevelList bitfield, int ran { if (numSeries > 0) { - *ptr-- = (short)((first + bitfield.Count - last) * IntPtr.Size); + *ptr-- = (short)((first + bitfield.Length - last) * IntPtr.Size); *ptr-- = numPtrs; *(void**)gcdesc = (void*)-numSeries; @@ -542,7 +542,7 @@ private static unsafe int CreateArrayGCDesc(LowLevelList bitfield, int ran return numSeries; } - private static unsafe int CreateGCDesc(LowLevelList bitfield, int size, bool isValueType, bool isStatic, void* gcdesc) + private static unsafe int CreateGCDesc(bool[] bitfield, int size, bool isValueType, bool isStatic, void* gcdesc) { int offs = 0; // if this type is a class we have to account for the gcdesc. @@ -558,7 +558,7 @@ private static unsafe int CreateGCDesc(LowLevelList bitfield, int size, bo int numSeries = 0; int i = 0; - while (i < bitfield.Count) + while (i < bitfield.Length) { if (bitfield[i]) { @@ -566,7 +566,7 @@ private static unsafe int CreateGCDesc(LowLevelList bitfield, int size, bo int seriesOffset = i * IntPtr.Size + offs; int seriesSize = 0; - while ((i < bitfield.Count) && (bitfield[i])) + while ((i < bitfield.Length) && (bitfield[i])) { seriesSize += IntPtr.Size; i++; 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 48bb6c91b6169d..3aae2b72821971 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 @@ -13,18 +13,6 @@ namespace Internal.Runtime.TypeLoader { - internal static class LowLevelListExtensions - { - public static void Expand(this LowLevelList list, int count) - { - if (list.Capacity < count) - list.Capacity = count; - - while (list.Count < count) - list.Add(default(T)); - } - } - internal class TypeBuilder { public TypeBuilder() @@ -447,17 +435,17 @@ internal void ParseNativeLayoutInfo(TypeBuilderState state, TypeDesc type) /// internal unsafe struct GCLayout { - private LowLevelList _bitfield; + private bool[] _bitfield; private unsafe void* _gcdesc; private int _size; private bool _isReferenceTypeGCLayout; public static GCLayout None { get { return default(GCLayout); } } - public static GCLayout SingleReference { get; } = new GCLayout(new LowLevelList(new bool[1] { true }), false); + public static GCLayout SingleReference { get; } = new GCLayout([true], false); public bool IsNone { get { return _bitfield == null && _gcdesc == null; } } - public GCLayout(LowLevelList bitfield, bool isReferenceTypeGCLayout) + public GCLayout(bool[] bitfield, bool isReferenceTypeGCLayout) { Debug.Assert(bitfield != null); @@ -473,7 +461,7 @@ public GCLayout(RuntimeTypeHandle rtth) Debug.Assert(MethodTable != null); _bitfield = null; - _isReferenceTypeGCLayout = false; // This field is only used for the LowLevelList path + _isReferenceTypeGCLayout = false; // This field is only used for the bool[] path _gcdesc = MethodTable->ContainsGCPointers ? (void**)MethodTable - 1 : null; _size = (int)MethodTable->BaseSize; } @@ -484,7 +472,7 @@ public GCLayout(RuntimeTypeHandle rtth) /// The bitfield to write a layout to (may be null, at which /// point it will be created and assigned). /// The offset at which we need to write the bitfield. - public void WriteToBitfield(LowLevelList bitfield, int offset) + public void WriteToBitfield(ref bool[] bitfield, int offset) { ArgumentNullException.ThrowIfNull(bitfield); @@ -495,12 +483,12 @@ public void WriteToBitfield(LowLevelList bitfield, int offset) Debug.Assert(_gcdesc != null ^ _bitfield != null); if (_bitfield != null) - MergeBitfields(bitfield, offset); + MergeBitfields(ref bitfield, offset); else - WriteGCDescToBitfield(bitfield, offset); + WriteGCDescToBitfield(ref bitfield, offset); } - private unsafe void WriteGCDescToBitfield(LowLevelList bitfield, int offset) + private unsafe void WriteGCDescToBitfield(ref bool[] bitfield, int offset) { int startIndex = offset / IntPtr.Size; @@ -513,7 +501,7 @@ private unsafe void WriteGCDescToBitfield(LowLevelList bitfield, int offse // Ensure capacity for the values we are about to write int capacity = startIndex + _size / IntPtr.Size - 2; - bitfield.Expand(capacity); + Array.Resize(ref bitfield, capacity); while (count-- >= 0) { @@ -528,25 +516,23 @@ private unsafe void WriteGCDescToBitfield(LowLevelList bitfield, int offse } } - private void MergeBitfields(LowLevelList outputBitfield, int offset) + private void MergeBitfields(ref bool[] outputBitfield, int offset) { int startIndex = offset / IntPtr.Size; // These routines represent the GC layout after the MethodTable pointer - // in an object, but the LowLevelList bitfield logically contains - // the EETypepointer if it is describing a reference type. So, skip the - // first value. + // in an object, but the bool[] bitfield logically contains the EETypepointer + // if it is describing a reference type. So, skip the first value. int itemsToSkip = _isReferenceTypeGCLayout ? 1 : 0; // Assert that we only skip a non-reported pointer. Debug.Assert(itemsToSkip == 0 || _bitfield[0] == false); // Ensure capacity for the values we are about to write - int capacity = startIndex + _bitfield.Count - itemsToSkip; - outputBitfield.Expand(capacity); - + int capacity = startIndex + _bitfield.Length - itemsToSkip; + Array.Resize(ref outputBitfield, capacity); - for (int i = itemsToSkip; i < _bitfield.Count; i++) + for (int i = itemsToSkip; i < _bitfield.Length; i++) { // We should never overwrite a TRUE value in the table. Debug.Assert(!outputBitfield[startIndex + i - itemsToSkip] || _bitfield[i]); 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 39915c06576a15..97f1c96d1d89dc 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 @@ -306,9 +306,11 @@ public ushort NumVTableSlots // Sentinel static to allow us to initialize _instanceLayout to something // and then detect that InstanceGCLayout should return null - private static LowLevelList s_emptyLayout = new LowLevelList(); +#pragma warning disable CA1825 // Can't use generic Array.Empty within type loader + private static bool[] s_emptyLayout = new bool[0]; +#pragma warning restore CA1825 - private LowLevelList _instanceGCLayout; + private bool[] _instanceGCLayout; /// /// The instance gc layout of a dynamically laid out type. @@ -324,14 +326,12 @@ public ushort NumVTableSlots /// If the type is a valuetype array, this is the layout of the valuetype held in the array if the type has GC reference fields /// Otherwise, it is the layout of the fields in the type. /// - public LowLevelList InstanceGCLayout + public bool[] InstanceGCLayout { get { if (_instanceGCLayout == null) { - LowLevelList instanceGCLayout; - if (TypeBeingBuilt is ArrayType) { if (!IsArrayOfReferenceTypes) @@ -340,8 +340,8 @@ public LowLevelList InstanceGCLayout TypeBuilder.GCLayout elementGcLayout = GetFieldGCLayout(arrayType.ElementType); if (!elementGcLayout.IsNone) { - instanceGCLayout = new LowLevelList(); - elementGcLayout.WriteToBitfield(instanceGCLayout, 0); + bool[] instanceGCLayout = s_emptyLayout; + elementGcLayout.WriteToBitfield(ref instanceGCLayout, 0); _instanceGCLayout = instanceGCLayout; } } From bdb88340f68eabe630d5e3ed28e25d0735e87793 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 4 Jun 2025 21:13:52 +0800 Subject: [PATCH 2/7] Cleanup empty layout input --- .../Runtime/TypeLoader/TypeBuilder.cs | 40 +++++++++---------- .../Runtime/TypeLoader/TypeBuilderState.cs | 6 +-- 2 files changed, 20 insertions(+), 26 deletions(-) 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 3aae2b72821971..4ed891ee6b152d 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 @@ -469,29 +469,23 @@ public GCLayout(RuntimeTypeHandle rtth) /// /// Writes this layout to the given bitfield. /// - /// The bitfield to write a layout to (may be null, at which - /// point it will be created and assigned). - /// The offset at which we need to write the bitfield. - public void WriteToBitfield(ref bool[] bitfield, int offset) + /// The layout in bitfield. + public bool[] WriteToBitfield() { - ArgumentNullException.ThrowIfNull(bitfield); - if (IsNone) - return; + return TypeBuilderState.s_emptyLayout; // Ensure exactly one of these two are set. Debug.Assert(_gcdesc != null ^ _bitfield != null); if (_bitfield != null) - MergeBitfields(ref bitfield, offset); + return MergeBitfields(); else - WriteGCDescToBitfield(ref bitfield, offset); + return WriteGCDescToBitfield(); } - private unsafe void WriteGCDescToBitfield(ref bool[] bitfield, int offset) + private unsafe bool[] WriteGCDescToBitfield() { - int startIndex = offset / IntPtr.Size; - void** ptr = (void**)_gcdesc; Debug.Assert(_gcdesc != null); @@ -500,8 +494,8 @@ private unsafe void WriteGCDescToBitfield(ref bool[] bitfield, int offset) Debug.Assert(count >= 0); // Ensure capacity for the values we are about to write - int capacity = startIndex + _size / IntPtr.Size - 2; - Array.Resize(ref bitfield, capacity); + int capacity = _size / IntPtr.Size - 2; + bool[] bitfield = new bool[capacity]; while (count-- >= 0) { @@ -512,14 +506,14 @@ private unsafe void WriteGCDescToBitfield(ref bool[] bitfield, int offset) Debug.Assert(offs >= 0); for (int i = 0; i < len; i++) - bitfield[startIndex + offs + i] = true; + bitfield[offs + i] = true; } + + return bitfield; } - private void MergeBitfields(ref bool[] outputBitfield, int offset) + private bool[] MergeBitfields() { - int startIndex = offset / IntPtr.Size; - // These routines represent the GC layout after the MethodTable pointer // in an object, but the bool[] bitfield logically contains the EETypepointer // if it is describing a reference type. So, skip the first value. @@ -529,16 +523,18 @@ private void MergeBitfields(ref bool[] outputBitfield, int offset) Debug.Assert(itemsToSkip == 0 || _bitfield[0] == false); // Ensure capacity for the values we are about to write - int capacity = startIndex + _bitfield.Length - itemsToSkip; - Array.Resize(ref outputBitfield, capacity); + int capacity = _bitfield.Length - itemsToSkip; + bool[] outputBitfield = new bool[capacity]; for (int i = itemsToSkip; i < _bitfield.Length; i++) { // We should never overwrite a TRUE value in the table. - Debug.Assert(!outputBitfield[startIndex + i - itemsToSkip] || _bitfield[i]); + Debug.Assert(!outputBitfield[i - itemsToSkip] || _bitfield[i]); - outputBitfield[startIndex + i - itemsToSkip] = _bitfield[i]; + outputBitfield[i - itemsToSkip] = _bitfield[i]; } + + return outputBitfield; } } 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 97f1c96d1d89dc..fbf1bcb557a92a 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 @@ -307,7 +307,7 @@ public ushort NumVTableSlots // Sentinel static to allow us to initialize _instanceLayout to something // and then detect that InstanceGCLayout should return null #pragma warning disable CA1825 // Can't use generic Array.Empty within type loader - private static bool[] s_emptyLayout = new bool[0]; + internal static bool[] s_emptyLayout = new bool[0]; #pragma warning restore CA1825 private bool[] _instanceGCLayout; @@ -340,9 +340,7 @@ public bool[] InstanceGCLayout TypeBuilder.GCLayout elementGcLayout = GetFieldGCLayout(arrayType.ElementType); if (!elementGcLayout.IsNone) { - bool[] instanceGCLayout = s_emptyLayout; - elementGcLayout.WriteToBitfield(ref instanceGCLayout, 0); - _instanceGCLayout = instanceGCLayout; + _instanceGCLayout = elementGcLayout.WriteToBitfield(); } } else From 54f9a78c547b298e21f9191cd52776054664fb96 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 5 Jun 2025 01:54:23 +0800 Subject: [PATCH 3/7] Cleanup _isReferenceTypeGCLayout --- .../Runtime/TypeLoader/TypeBuilder.cs | 37 ++----------------- 1 file changed, 3 insertions(+), 34 deletions(-) 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 4ed891ee6b152d..2e4789008fdc43 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 @@ -438,21 +438,19 @@ internal unsafe struct GCLayout private bool[] _bitfield; private unsafe void* _gcdesc; private int _size; - private bool _isReferenceTypeGCLayout; public static GCLayout None { get { return default(GCLayout); } } - public static GCLayout SingleReference { get; } = new GCLayout([true], false); + public static GCLayout SingleReference { get; } = new GCLayout([true]); public bool IsNone { get { return _bitfield == null && _gcdesc == null; } } - public GCLayout(bool[] bitfield, bool isReferenceTypeGCLayout) + public GCLayout(bool[] bitfield) { Debug.Assert(bitfield != null); _bitfield = bitfield; _gcdesc = null; _size = 0; - _isReferenceTypeGCLayout = isReferenceTypeGCLayout; } public GCLayout(RuntimeTypeHandle rtth) @@ -461,7 +459,6 @@ public GCLayout(RuntimeTypeHandle rtth) Debug.Assert(MethodTable != null); _bitfield = null; - _isReferenceTypeGCLayout = false; // This field is only used for the bool[] path _gcdesc = MethodTable->ContainsGCPointers ? (void**)MethodTable - 1 : null; _size = (int)MethodTable->BaseSize; } @@ -478,10 +475,7 @@ public bool[] WriteToBitfield() // Ensure exactly one of these two are set. Debug.Assert(_gcdesc != null ^ _bitfield != null); - if (_bitfield != null) - return MergeBitfields(); - else - return WriteGCDescToBitfield(); + return _bitfield ?? WriteGCDescToBitfield(); } private unsafe bool[] WriteGCDescToBitfield() @@ -511,31 +505,6 @@ private unsafe bool[] WriteGCDescToBitfield() return bitfield; } - - private bool[] MergeBitfields() - { - // These routines represent the GC layout after the MethodTable pointer - // in an object, but the bool[] bitfield logically contains the EETypepointer - // if it is describing a reference type. So, skip the first value. - int itemsToSkip = _isReferenceTypeGCLayout ? 1 : 0; - - // Assert that we only skip a non-reported pointer. - Debug.Assert(itemsToSkip == 0 || _bitfield[0] == false); - - // Ensure capacity for the values we are about to write - int capacity = _bitfield.Length - itemsToSkip; - bool[] outputBitfield = new bool[capacity]; - - for (int i = itemsToSkip; i < _bitfield.Length; i++) - { - // We should never overwrite a TRUE value in the table. - Debug.Assert(!outputBitfield[i - itemsToSkip] || _bitfield[i]); - - outputBitfield[i - itemsToSkip] = _bitfield[i]; - } - - return outputBitfield; - } } private unsafe void AllocateRuntimeType(TypeDesc type) From 4b183170726ddf42f9a79c2088b57cc8316eb87a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 5 Jun 2025 09:37:17 +0800 Subject: [PATCH 4/7] Use Array.Empty --- .../src/Internal/Runtime/TypeLoader/TypeBuilderState.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 fbf1bcb557a92a..29fcb6409eaa3e 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 @@ -306,9 +306,7 @@ public ushort NumVTableSlots // Sentinel static to allow us to initialize _instanceLayout to something // and then detect that InstanceGCLayout should return null -#pragma warning disable CA1825 // Can't use generic Array.Empty within type loader - internal static bool[] s_emptyLayout = new bool[0]; -#pragma warning restore CA1825 + internal static readonly bool[] s_emptyLayout = []; private bool[] _instanceGCLayout; From 3e1e1d87ac9cd4b939b946b6fb6d50f2dd6bf297 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 5 Jun 2025 22:24:29 +0800 Subject: [PATCH 5/7] Update name and sentinel --- .../src/Internal/Runtime/TypeLoader/TypeBuilder.cs | 8 ++++---- .../src/Internal/Runtime/TypeLoader/TypeBuilderState.cs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) 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 2e4789008fdc43..6f8b02d93ead60 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 @@ -464,13 +464,13 @@ public GCLayout(RuntimeTypeHandle rtth) } /// - /// Writes this layout to the given bitfield. + /// Gets this layout in bitfield array. /// /// The layout in bitfield. - public bool[] WriteToBitfield() + public bool[] AsBitfield() { - if (IsNone) - return TypeBuilderState.s_emptyLayout; + // This method should only be called when not none. + Debug.Assert(!IsNone); // Ensure exactly one of these two are set. Debug.Assert(_gcdesc != null ^ _bitfield != null); 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 29fcb6409eaa3e..f351a128572459 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 @@ -306,7 +306,7 @@ public ushort NumVTableSlots // Sentinel static to allow us to initialize _instanceLayout to something // and then detect that InstanceGCLayout should return null - internal static readonly bool[] s_emptyLayout = []; + private static readonly bool[] s_emptyLayout = []; private bool[] _instanceGCLayout; @@ -338,7 +338,7 @@ public bool[] InstanceGCLayout TypeBuilder.GCLayout elementGcLayout = GetFieldGCLayout(arrayType.ElementType); if (!elementGcLayout.IsNone) { - _instanceGCLayout = elementGcLayout.WriteToBitfield(); + _instanceGCLayout = elementGcLayout.AsBitfield(); } } else From 7a0a2f973d7565e0805b965ab9f9d349550d3536 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 5 Jun 2025 23:33:42 +0800 Subject: [PATCH 6/7] Clean unreachable path --- .../Runtime/TypeLoader/EETypeCreator.cs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) 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 a4474f8d7f4b07..c04576180dbbd6 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 @@ -399,27 +399,20 @@ private static void CreateInstanceGCDesc(TypeBuilderState state, MethodTable* pT pEEType->ContainsGCPointers = false; } } - else if (gcBitfield != null) + else { - if (cbGCDesc != 0) + Debug.Assert(gcBitfield == null); + + if (pTemplateEEType != null) { - pEEType->ContainsGCPointers = true; - CreateGCDesc(gcBitfield, baseSize, isValueType, false, ((void**)pEEType) - 1); + Buffer.MemoryCopy((byte*)pTemplateEEType - cbGCDesc, (byte*)pEEType - cbGCDesc, cbGCDesc, cbGCDesc); + pEEType->ContainsGCPointers = pTemplateEEType->ContainsGCPointers; } else { pEEType->ContainsGCPointers = false; } } - else if (pTemplateEEType != null) - { - Buffer.MemoryCopy((byte*)pTemplateEEType - cbGCDesc, (byte*)pEEType - cbGCDesc, cbGCDesc, cbGCDesc); - pEEType->ContainsGCPointers = pTemplateEEType->ContainsGCPointers; - } - else - { - pEEType->ContainsGCPointers = false; - } } private static unsafe int GetInstanceGCDescSize(TypeBuilderState state, MethodTable* pTemplateEEType, bool isValueType, bool isArray) From 6c83da5df817fc1b80e4a8800d3202612922a890 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 7 Jun 2025 16:04:18 +0800 Subject: [PATCH 7/7] More unreachable --- .../Runtime/TypeLoader/EETypeCreator.cs | 83 +++---------------- 1 file changed, 10 insertions(+), 73 deletions(-) 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 c04576180dbbd6..cccb25742a8aa5 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 @@ -435,18 +435,18 @@ private static unsafe int GetInstanceGCDescSize(TypeBuilderState state, MethodTa return series > 0 ? (series + 2) * IntPtr.Size : 0; } } - else if (gcBitfield != null) - { - int series = CreateGCDesc(gcBitfield, 0, isValueType, false, null); - return series > 0 ? (series * 2 + 1) * IntPtr.Size : 0; - } - else if (pTemplateEEType != null) - { - return RuntimeAugments.GetGCDescSize(pTemplateEEType->ToRuntimeTypeHandle()); - } else { - return 0; + Debug.Assert(gcBitfield == null); + + if (pTemplateEEType != null) + { + return RuntimeAugments.GetGCDescSize(pTemplateEEType->ToRuntimeTypeHandle()); + } + else + { + return 0; + } } } @@ -535,69 +535,6 @@ private static unsafe int CreateArrayGCDesc(bool[] bitfield, int rank, bool isSz return numSeries; } - private static unsafe int CreateGCDesc(bool[] bitfield, int size, bool isValueType, bool isStatic, void* gcdesc) - { - int offs = 0; - // if this type is a class we have to account for the gcdesc. - if (isValueType) - offs = IntPtr.Size; - - if (bitfield == null) - return 0; - - void** ptr = (void**)gcdesc - 1; - - int* staticPtr = isStatic ? ((int*)gcdesc + 1) : null; - - int numSeries = 0; - int i = 0; - while (i < bitfield.Length) - { - if (bitfield[i]) - { - numSeries++; - int seriesOffset = i * IntPtr.Size + offs; - int seriesSize = 0; - - while ((i < bitfield.Length) && (bitfield[i])) - { - seriesSize += IntPtr.Size; - i++; - } - - - if (gcdesc != null) - { - if (staticPtr != null) - { - *staticPtr++ = seriesSize; - *staticPtr++ = seriesOffset; - } - else - { - seriesSize -= size; - *ptr-- = (void*)seriesOffset; - *ptr-- = (void*)seriesSize; - } - } - } - else - { - i++; - } - } - - if (gcdesc != null) - { - if (staticPtr != null) - *(int*)gcdesc = numSeries; - else - *(void**)gcdesc = (void*)numSeries; - } - - return numSeries; - } - public static RuntimeTypeHandle CreateFunctionPointerEEType(uint hashCodeOfNewType, RuntimeTypeHandle returnTypeHandle, RuntimeTypeHandle[] parameterHandles, FunctionPointerType functionPointerType) { TypeBuilderState state = new TypeBuilderState(functionPointerType);