Allow exact devirtualization for value-type variant instantiations in ilc#129905
Open
jtschuster wants to merge 1 commit into
Open
Allow exact devirtualization for value-type variant instantiations in ilc#129905jtschuster wants to merge 1 commit into
jtschuster wants to merge 1 commit into
Conversation
… NativeAOT PR dotnet#123476 made getExactClasses bail for any variant type to avoid unsoundly folding variant casts (e.g. Action<string> vs Action<object>). That guard is over-broad: variance conversions only happen through reference conversions of the variant type arguments, so a type instantiated with only value-type variant arguments cannot be substituted via variance and its implementor list is still complete. This regressed exact devirtualization of the contravariant IEqualityComparer<T> calls in Dictionary<TKey, TValue>.FindValue for value-type keys, inflating the method and slowing the hot path (issue dotnet#129895). Bail only when a variant generic parameter is instantiated with a reference (GC) type, matching CastingHelper's IsBoxedAndCanCastTo which requires IsGCPointer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refines CorInfoImpl.getExactClasses behavior in the NativeAOT ILCompiler JIT interface so that variance only blocks exact-class reporting when variant generic parameters are instantiated with reference types, restoring exact devirtualization opportunities for value-type instantiations.
Changes:
- Split the
type == null || type.HasVarianceearly-bail to allow more granular variance handling. - Introduce a helper to detect whether a variant type instantiation includes any reference-type variant arguments.
- Use that helper to decide when variance makes
getExactClassesunsound.
Comment on lines
+2345
to
+2346
| if (((GenericParameterDesc)genericParameters[i]).Variance != GenericVariance.None | ||
| && typeInstantiation[i].IsGCPointer) |
Comment on lines
+2296
to
+2298
| // so reporting an exact class set would be unsound. This only happens through | ||
| // reference conversions of the variant arguments, so it's still safe when every | ||
| // variant argument is a value type (e.g. the contravariant IEqualityComparer<int> |
Member
There was a problem hiding this comment.
This is not true, variance can play role for valuetypes too. I had no confidence in being able to capture all the rules when variance and whole program analysis is involved. We had several bugs in this area.
// True
Console.WriteLine(G() is ICollection<uint>);
static object G() => new int[0];
Open
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Dictionary<int,int>'s getter regressed slightly in .NET 11 NativeAOT (see semi-related #129895).
PR #123476 made getExactClasses bail for any variant type to avoid unsoundly folding variant casts (e.g. Action vs Action). That guard is slightly over-broad: variance is only relevant for reference types and can be ignored for ValueType type arguments.
This regressed exact devirtualization of the contravariant IEqualityComparer calls in Dictionary<TKey, TValue>.FindValue for value-type keys, inflating the method and slowing the hot path.
We can tighten the condition for bailing early and do so only when a variant generic parameter is instantiated with a reference type.