Skip to content

Cleanup LowLevelList usage in GCLayout #116316

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

Merged
merged 7 commits into from
Jun 8, 2025
Merged

Conversation

huoyaoyuan
Copy link
Member

Extracted from #109114

The merging and _isReferenceTypeGCLayout paths looks unused. Not sure whether I missed anything.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Jun 4, 2025
Copy link
Contributor

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.

@@ -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<bool> s_emptyLayout = new LowLevelList<bool>();
#pragma warning disable CA1825 // Can't use generic Array.Empty<T> within type loader
Copy link
Member

Choose a reason for hiding this comment

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

This is not the case anymore. It is fine use Array.Empty here.

@huoyaoyuan
Copy link
Member Author

Test failure is #116261

@@ -306,9 +306,9 @@ public ushort NumVTableSlots

// Sentinel static to allow us to initialize _instanceLayout to something
// and then detect that InstanceGCLayout should return null
private static LowLevelList<bool> s_emptyLayout = new LowLevelList<bool>();
internal static readonly bool[] s_emptyLayout = [];
Copy link
Member

Choose a reason for hiding this comment

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

You should not need to cache in a static field - it is a deoptimization to cache it.

Copy link
Member Author

Choose a reason for hiding this comment

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

The empty array instance is used as a sentinel and compared in reference. If WriteGCDescToBitfield produces empty layout, it may be treated differently. Comparing to the collection literal expression looks weird here.

@@ -473,37 +459,27 @@ public GCLayout(RuntimeTypeHandle rtth)
Debug.Assert(MethodTable != null);

_bitfield = null;
_isReferenceTypeGCLayout = false; // This field is only used for the LowLevelList<bool> path
_gcdesc = MethodTable->ContainsGCPointers ? (void**)MethodTable - 1 : null;
_size = (int)MethodTable->BaseSize;
}

/// <summary>
/// Writes this layout to the given bitfield.
Copy link
Member

Choose a reason for hiding this comment

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

There is no "given bitfield" anymore. This comment should be updated.

Also, should the method be renamed to GetBitField? It is not necessarily "writing to" anything.

if (IsNone)
return;
return TypeBuilderState.s_emptyLayout;
Copy link
Member

Choose a reason for hiding this comment

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

I think this sentinel should be kelp private to TypeBuilderState. This check can deleted here - the one place that calls this method does this only when IsNone returns false.

@@ -542,7 +542,7 @@ private static unsafe int CreateArrayGCDesc(LowLevelList<bool> bitfield, int ran
return numSeries;
}

private static unsafe int CreateGCDesc(LowLevelList<bool> bitfield, int size, bool isValueType, bool isStatic, void* gcdesc)
private static unsafe int CreateGCDesc(bool[] bitfield, int size, bool isValueType, bool isStatic, void* gcdesc)
Copy link
Member

Choose a reason for hiding this comment

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

This method looks unreachable given that InstanceGCLayout only returns non-null layout for arrays. Delete it?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's also called in EETypeCreator.CreateEETypeWorker, which should be reachable.

Copy link
Member

Choose a reason for hiding this comment

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

I believe that the other call is unreachable as well. One of them computes just the size, the other one (that you have deleted here) fills in the memory that was allocated based the size returned from the first call.

Copy link
Member Author

Choose a reason for hiding this comment

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

CreateEETypeWorker calls GetInstanceGCDescSize for size and CreateInstanceGCDesc for content. Both methods are called once now.

Copy link
Member

@jkotas jkotas Jun 7, 2025

Choose a reason for hiding this comment

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

There is only one place in GetInstanceGCDescSize that calls CreateGCDesc. My point is that that codepath is unreachable and it can be deleted, in similar way how you deleted it CreateGCDesc from CreateInstanceGCDesc.

If I am missing something and CreateGCDesc is still reachable, it would be useful to find a test that hits it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, the code within GetInstanceGCDescSize also has a dead path. Now the control flow should be the same with CreateInstanceGCDesc.

@jkotas
Copy link
Member

jkotas commented Jun 7, 2025

/azp run runtime-nativeaot-outerloop

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

Thanks

@jkotas
Copy link
Member

jkotas commented Jun 8, 2025

/ba-g deadletter

@jkotas jkotas merged commit 0f2bfae into dotnet:main Jun 8, 2025
111 of 117 checks passed
@huoyaoyuan huoyaoyuan deleted the gclayout branch June 8, 2025 02:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-NativeAOT-coreclr community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants