diff --git a/src/coreclr/nativeaot/Common/src/Internal/Runtime/TypeLoader/ExternalReferencesTable.cs b/src/coreclr/nativeaot/Common/src/Internal/Runtime/TypeLoader/ExternalReferencesTable.cs index c78c8463a7638..dcc61676bea58 100644 --- a/src/coreclr/nativeaot/Common/src/Internal/Runtime/TypeLoader/ExternalReferencesTable.cs +++ b/src/coreclr/nativeaot/Common/src/Internal/Runtime/TypeLoader/ExternalReferencesTable.cs @@ -56,11 +56,6 @@ public RuntimeTypeHandle GetRuntimeTypeHandleFromIndex(uint index) return RuntimeAugments.CreateRuntimeTypeHandle(GetIntPtrFromIndex(index)); } - public IntPtr GetGenericDictionaryFromIndex(uint index) - { - return GetIntPtrFromIndex(index); - } - public unsafe IntPtr GetAddressFromIndex(uint index) { if (index >= _elementsCount) diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs index 3ec00d4bfd09b..51fd7d251dc2e 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs @@ -897,14 +897,12 @@ private struct InvokeMapEntryDataEnumerator 0)); - return true; - } - - if ((_flags & InvokeTableFlags.IsUniversalCanonicalEntry) != 0) - { - // _nameAndSignature should have been read from the InvokeMap entry directly! - Debug.Fail("Universal canonical entries do NOT have dictionary entries!"); - return false; - } - - RuntimeTypeHandle dummy1; - bool success = TypeLoaderEnvironment.Instance.TryGetGenericMethodComponents(_entryDictionary, out dummy1, out _nameAndSignature, out _entryMethodInstantiation); - Debug.Assert(success && dummy1.Equals(_entryType) && _nameAndSignature != null && _entryMethodInstantiation != null && _entryMethodInstantiation.Length > 0); - return success; - } } public bool TryGetMetadataForTypeMethodNameAndSignature(RuntimeTypeHandle declaringTypeHandle, MethodNameAndSignature nameAndSignature, out QMethodDefinition methodHandle) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs index ddc81945ae7b2..335817555d2e1 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs @@ -7,8 +7,6 @@ using Internal.Text; using Internal.TypeSystem; -using CombinedDependencyList = System.Collections.Generic.List.CombinedDependencyListEntry>; - namespace ILCompiler.DependencyAnalysis { /// @@ -198,13 +196,7 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde protected override TypeSystemContext Context => _owningMethod.Context; public override TypeSystemEntity OwningEntity => _owningMethod; public MethodDesc OwningMethod => _owningMethod; - public override bool HasConditionalStaticDependencies => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) - { - CombinedDependencyList list = null; - factory.MetadataManager.GetConditionalDependenciesDueToMethodGenericDictionary(ref list, factory, _owningMethod); - return list ?? (IEnumerable)System.Array.Empty(); - } + public override bool HasConditionalStaticDependencies => false; protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) { @@ -247,8 +239,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact // Make sure the dictionary can also be populated dependencies.Add(factory.ShadowConcreteMethod(_owningMethod), "Dictionary contents"); - factory.MetadataManager.GetDependenciesForGenericDictionary(ref dependencies, factory, _owningMethod); - return dependencies; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs index 62480431a8b37..a9aad5606a5a6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs @@ -1708,6 +1708,7 @@ public sealed class NativeLayoutFieldLdTokenGenericDictionarySlotNode : NativeLa public NativeLayoutFieldLdTokenGenericDictionarySlotNode(FieldDesc field) { + Debug.Assert(field.OwningType.IsRuntimeDeterminedSubtype); _field = field; } @@ -1717,12 +1718,21 @@ public NativeLayoutFieldLdTokenGenericDictionarySlotNode(FieldDesc field) public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) { - yield return new DependencyListEntry(factory.NativeLayout.FieldLdTokenVertex(_field), "Field Signature"); + var result = new DependencyList + { + { factory.NativeLayout.FieldLdTokenVertex(_field), "Field Signature" } + }; foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_field.OwningType)) { - yield return new DependencyListEntry(dependency, "template construction dependency"); + result.Add(dependency, "template construction dependency"); } + + var canonOwningType = (InstantiatedType)_field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific); + FieldDesc canonField = factory.TypeSystemContext.GetFieldForInstantiatedType(_field.GetTypicalFieldDefinition(), canonOwningType); + factory.MetadataManager.GetDependenciesDueToLdToken(ref result, factory, canonField); + + return result; } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) @@ -1747,18 +1757,25 @@ public NativeLayoutMethodLdTokenGenericDictionarySlotNode(MethodDesc method) public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) { - yield return new DependencyListEntry(factory.NativeLayout.MethodLdTokenVertex(_method), "Method Signature"); + var result = new DependencyList + { + { factory.NativeLayout.MethodLdTokenVertex(_method), "Method Signature" } + }; foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType)) { - yield return new DependencyListEntry(dependency, "template construction dependency for method OwningType"); + result.Add(dependency, "template construction dependency for method OwningType"); } foreach (var type in _method.Instantiation) { foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(type)) - yield return new DependencyListEntry(dependency, "template construction dependency for method Instantiation types"); + result.Add(dependency, "template construction dependency for method Instantiation types"); } + + factory.MetadataManager.GetDependenciesDueToLdToken(ref result, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); + + return result; } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs index e1249f035f902..f87f1332b3a81 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs @@ -176,6 +176,8 @@ public IEnumerable TemplateConstructableTypes(TypeDesc type) { yield return _factory.NativeLayout.TemplateTypeLayout(arrayCanonicalType); } + + yield return _factory.MaximallyConstructableType(arrayCanonicalType); } while (type.IsParameterizedType) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs index 70713b3431cd8..b1111d76b846f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -957,6 +957,9 @@ internal TypeGVMEntriesNode TypeGVMEntries(TypeDesc type) private NodeCache _reflectedMethods; public ReflectedMethodNode ReflectedMethod(MethodDesc method) { + // We track reflectability at canonical method body level + method = method.GetCanonMethodTarget(CanonicalFormKind.Specific); + return _reflectedMethods.GetOrAdd(method); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedMethodNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedMethodNode.cs index 729bf52019277..0696fe9eff8cb 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedMethodNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedMethodNode.cs @@ -24,8 +24,7 @@ public class ReflectedMethodNode : DependencyNodeCore public ReflectedMethodNode(MethodDesc method) { - Debug.Assert(!method.IsCanonicalMethod(CanonicalFormKind.Any) || - method.GetCanonMethodTarget(CanonicalFormKind.Specific) == method); + Debug.Assert(method.GetCanonMethodTarget(CanonicalFormKind.Specific) == method); _method = method; } @@ -53,12 +52,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto dependencies.Add(factory.ReflectedMethod(typicalMethod), "Definition of the reflectable method"); } - MethodDesc canonMethod = _method.GetCanonMethodTarget(CanonicalFormKind.Specific); - if (canonMethod != _method) - { - dependencies.Add(factory.ReflectedMethod(canonMethod), "Canonical version of the reflectable method"); - } - // Make sure we generate the method body and other artifacts. if (MetadataManager.IsMethodSupportedInReflectionInvoke(_method)) { @@ -82,11 +75,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto if (!_method.IsAbstract) { - dependencies.Add(factory.MethodEntrypoint(canonMethod), "Body of a reflectable method"); - - if (_method.HasInstantiation - && _method != canonMethod) - dependencies.Add(factory.MethodGenericDictionary(_method), "Dictionary of a reflectable method"); + dependencies.Add(factory.MethodEntrypoint(_method), "Body of a reflectable method"); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs index b541f52352055..08c3cb9e31f6c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs @@ -50,6 +50,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) public static void AddDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { Debug.Assert(factory.MetadataManager.IsReflectionInvokable(method)); + Debug.Assert(method.GetCanonMethodTarget(CanonicalFormKind.Specific) == method); dependencies ??= new DependencyList(); @@ -101,7 +102,7 @@ static bool ContainsFunctionPointers(TypeDesc type) } if (method.OwningType.IsValueType && !method.Signature.IsStatic) - dependencies.Add(factory.ExactCallableAddress(method, isUnboxingStub: true), "Reflection unboxing stub"); + dependencies.Add(factory.MethodEntrypoint(method, unboxingStub: true), "Reflection unboxing stub"); // If the method is defined in a different module than this one, a metadata token isn't known for performing the reference // Use a name/sig reference instead. @@ -113,12 +114,13 @@ static bool ContainsFunctionPointers(TypeDesc type) if (method.HasInstantiation) { - if (method.IsCanonicalMethod(CanonicalFormKind.Universal)) + if (method.IsCanonicalMethod(CanonicalFormKind.Any)) { - dependencies.Add(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method)), - "UniversalCanon signature of method"); + dependencies.Add(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())), + "Signature of canonical method"); } - else if (!method.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg() || method.IsAbstract) + + if (!method.IsCanonicalMethod(CanonicalFormKind.Universal)) { foreach (var instArg in method.Instantiation) { @@ -150,6 +152,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { MethodDesc method = mappingEntry.Entity; + Debug.Assert(method == method.GetCanonMethodTarget(CanonicalFormKind.Specific)); + if (!factory.MetadataManager.ShouldMethodBeInInvokeMap(method)) continue; @@ -158,7 +162,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if (method.HasInstantiation) flags |= InvokeTableFlags.IsGenericMethod; - if (method.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg()) + if (method.RequiresInstArg()) { bool goesThroughInstantiatingUnboxingThunk = method.OwningType.IsValueType && !method.Signature.IsStatic && !method.HasInstantiation; if (!goesThroughInstantiatingUnboxingThunk) @@ -213,7 +217,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(_externalReferences.GetIndex( - factory.MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific), + factory.MethodEntrypoint(method, unboxingStub: method.OwningType.IsValueType && !method.Signature.IsStatic)))); } @@ -226,12 +230,13 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if ((flags & InvokeTableFlags.IsGenericMethod) != 0) { - if ((flags & InvokeTableFlags.IsUniversalCanonicalEntry) != 0) + if ((flags & InvokeTableFlags.RequiresInstArg) != 0) { - var nameAndSigGenericMethod = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method)); + var nameAndSigGenericMethod = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)nameAndSigGenericMethod.SavedVertex.VertexOffset)); } - else if ((flags & InvokeTableFlags.RequiresInstArg) == 0 || (flags & InvokeTableFlags.HasEntrypoint) == 0) + + if ((flags & InvokeTableFlags.IsUniversalCanonicalEntry) == 0) { VertexSequence args = new VertexSequence(); for (int i = 0; i < method.Instantiation.Length; i++) @@ -241,14 +246,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) } vertex = writer.GetTuple(vertex, args); } - else - { - uint dictionaryId = _externalReferences.GetIndex(factory.MethodGenericDictionary(method)); - vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(dictionaryId)); - } } - int hashCode = method.GetCanonMethodTarget(CanonicalFormKind.Specific).OwningType.GetHashCode(); + int hashCode = method.OwningType.GetHashCode(); typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex)); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs index c01ba9ed2dccf..eab08b1bcafd2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs @@ -52,12 +52,13 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact && _targetMethod.HasInstantiation && _targetMethod.IsVirtual) { dependencies ??= new DependencyList(); - dependencies.Add(factory.GVMDependencies(_targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific)), "GVM dependencies for runtime method handle"); + MethodDesc canonMethod = _targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); + dependencies.Add(factory.GVMDependencies(canonMethod), "GVM dependencies for runtime method handle"); // GVM analysis happens on canonical forms, but this is potentially injecting new genericness // into the system. Ensure reflection analysis can still see this. if (_targetMethod.IsAbstract) - factory.MetadataManager.GetDependenciesDueToMethodCodePresence(ref dependencies, factory, _targetMethod, methodIL: null); + factory.MetadataManager.GetDependenciesDueToMethodCodePresence(ref dependencies, factory, canonMethod, methodIL: null); } factory.MetadataManager.GetDependenciesDueToLdToken(ref dependencies, factory, _targetMethod); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/GeneratingMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/GeneratingMetadataManager.cs index 381a81ba82e03..14f1bdfdcee8d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/GeneratingMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/GeneratingMetadataManager.cs @@ -131,7 +131,6 @@ record ??= transformed.GetTransformedTypeReference(definition); typeMappings.Add(new MetadataMapping(definition, writer.GetRecordHandle(record))); } - HashSet canonicalGenericMethods = new HashSet(); foreach (var method in GetReflectableMethods()) { if (method.IsGenericMethodDefinition || method.OwningType.IsGenericDefinition) @@ -140,11 +139,9 @@ record ??= transformed.GetTransformedTypeReference(definition); continue; } - if ((method.HasInstantiation && method.IsCanonicalMethod(CanonicalFormKind.Specific)) - || (!method.HasInstantiation && method.GetCanonMethodTarget(CanonicalFormKind.Specific) != method)) + if (method.GetCanonMethodTarget(CanonicalFormKind.Specific) != method) { - // Methods that are not in their canonical form are not interesting with the exception - // of generic methods: their dictionaries convey their identity. + // Methods that are not in their canonical form are not interesting continue; } @@ -154,10 +151,6 @@ record ??= transformed.GetTransformedTypeReference(definition); if ((GetMetadataCategory(method) & MetadataCategory.RuntimeMapping) == 0) continue; - // If we already added a canonically equivalent generic method, skip this one. - if (method.HasInstantiation && !canonicalGenericMethods.Add(method.GetCanonMethodTarget(CanonicalFormKind.Specific))) - continue; - MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition()); if (record != null) @@ -168,19 +161,16 @@ record ??= transformed.GetTransformedTypeReference(definition); foreach (var field in GetFieldsWithRuntimeMapping()) { FieldDesc fieldToAdd = field; - if (!field.IsStatic) + TypeDesc canonOwningType = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific); + if (canonOwningType.IsCanonicalSubtype(CanonicalFormKind.Any)) { - TypeDesc canonOwningType = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific); - if (canonOwningType != field.OwningType) - { - FieldDesc canonField = _typeSystemContext.GetFieldForInstantiatedType(field.GetTypicalFieldDefinition(), (InstantiatedType)canonOwningType); + FieldDesc canonField = _typeSystemContext.GetFieldForInstantiatedType(field.GetTypicalFieldDefinition(), (InstantiatedType)canonOwningType); - // If we already added a canonically equivalent field, skip this one. - if (!canonicalFields.Add(canonField)) - continue; + // If we already added a canonically equivalent field, skip this one. + if (!canonicalFields.Add(canonField)) + continue; - fieldToAdd = canonField; - } + fieldToAdd = canonField; } Field record = transformed.GetTransformedFieldDefinition(fieldToAdd.GetTypicalFieldDefinition()); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index f848eb3496b1f..6f06532a8951f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -257,9 +257,6 @@ protected virtual void Graph_NewMarkedNode(DependencyNodeCore obj) if (dictionaryNode != null) { _genericDictionariesGenerated.Add(dictionaryNode); - - if (dictionaryNode.OwningEntity is MethodDesc method && AllMethodsCanBeReflectable) - _reflectableMethods.Add(method); } if (obj is InterfaceDispatchCellNode dispatchCell) @@ -531,12 +528,6 @@ public void GetDependenciesDueToMethodCodePresence(ref DependencyList dependenci GetDependenciesDueToMethodCodePresenceInternal(ref dependencies, factory, method, methodIL); } - public virtual void GetConditionalDependenciesDueToMethodGenericDictionary(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc method) - { - // MetadataManagers can override this to provide additional dependencies caused by the presence of - // method generic dictionary. - } - public virtual void GetConditionalDependenciesDueToMethodCodePresence(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc method) { // MetadataManagers can override this to provide additional dependencies caused by the presence of @@ -903,10 +894,6 @@ public virtual DependencyList GetDependenciesForCustomAttribute(NodeFactory fact return null; } - public virtual void GetDependenciesForGenericDictionary(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) - { - } - public virtual void NoteOverridingMethod(MethodDesc baseMethod, MethodDesc overridingMethod) { } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs index 61b43a2195b79..2e72c95dcc35a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs @@ -28,20 +28,14 @@ public static void RootType(IRootingServiceProvider rootProvider, TypeDesc type, { rootProvider.AddReflectionRoot(type, reason); - InstantiatedType fallbackNonCanonicalOwningType = null; - // Instantiate generic types over something that will be useful at runtime if (type.IsGenericDefinition) { - Instantiation canonInst = TypeExtensions.GetInstantiationThatMeetsConstraints(type.Instantiation, allowCanon: true); - if (canonInst.IsNull) + Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(type.Instantiation, allowCanon: true); + if (inst.IsNull) return; - Instantiation concreteInst = TypeExtensions.GetInstantiationThatMeetsConstraints(type.Instantiation, allowCanon: false); - if (!concreteInst.IsNull) - fallbackNonCanonicalOwningType = ((MetadataType)type).MakeInstantiatedType(concreteInst); - - type = ((MetadataType)type).MakeInstantiatedType(canonInst); + type = ((MetadataType)type).MakeInstantiatedType(inst); rootProvider.AddReflectionRoot(type, reason); } @@ -57,30 +51,15 @@ public static void RootType(IRootingServiceProvider rootProvider, TypeDesc type, if (type.IsDefType) { - foreach (var method in type.GetMethods()) + foreach (var method in type.ConvertToCanonForm(CanonicalFormKind.Specific).GetMethods()) { if (method.HasInstantiation) { - // Make a non-canonical instantiation. - // We currently have a file format limitation that requires generic methods to be concrete. - // A rooted canonical method body is not visible to the reflection mapping tables. - Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(method.Instantiation, allowCanon: false); - + Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(method.Instantiation, allowCanon: true); if (inst.IsNull) - { - // Can't root anything useful - } - else if (!method.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any)) - { - // Owning type is not canonical, can use the instantiation directly. - TryRootMethod(rootProvider, method.MakeInstantiatedMethod(inst), reason); - } - else if (fallbackNonCanonicalOwningType != null) - { - // We have a fallback non-canonical type we can root a body on - MethodDesc alternateMethod = method.Context.GetMethodForInstantiatedType(method.GetTypicalMethodDefinition(), fallbackNonCanonicalOwningType); - TryRootMethod(rootProvider, alternateMethod.MakeInstantiatedMethod(inst), reason); - } + continue; + + TryRootMethod(rootProvider, method.MakeInstantiatedMethod(inst), reason); } else { @@ -172,7 +151,7 @@ public static bool TryGetDependenciesForReflectedMethod(ref DependencyList depen if (method.OwningType.IsGenericDefinition || method.OwningType.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) { TypeDesc owningType = method.OwningType.GetTypeDefinition(); - Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(owningType.Instantiation, allowCanon: !method.HasInstantiation); + Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(owningType.Instantiation, allowCanon: true); if (inst.IsNull) { return false; @@ -187,7 +166,7 @@ public static bool TryGetDependenciesForReflectedMethod(ref DependencyList depen { method = method.GetMethodDefinition(); - Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(method.Instantiation, allowCanon: false); + Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(method.Instantiation, allowCanon: true); if (inst.IsNull) { return false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs index 5403534d411ef..bfb48d1b27600 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs @@ -137,12 +137,9 @@ protected override void Graph_NewMarkedNode(DependencyNodeCore obj) if (reflectedFieldNode != null) { FieldDesc field = reflectedFieldNode.Field; - DefType fieldOwningType = field.OwningType; // Filter out to those that make sense to have in the mapping tables - if (!fieldOwningType.IsGenericDefinition - && !field.IsLiteral - && (!fieldOwningType.IsCanonicalSubtype(CanonicalFormKind.Specific) || !field.IsStatic)) + if (!field.OwningType.IsGenericDefinition && !field.IsLiteral) { Debug.Assert((GetMetadataCategory(field) & MetadataCategory.RuntimeMapping) != 0); _fieldsWithRuntimeMapping.Add(field); @@ -577,26 +574,6 @@ protected override void GetDependenciesDueToMethodCodePresenceInternal(ref Depen } } - public override void GetConditionalDependenciesDueToMethodGenericDictionary(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc method) - { - Debug.Assert(!method.IsSharedByGenericInstantiations && method.HasInstantiation && method.GetCanonMethodTarget(CanonicalFormKind.Specific) != method); - - if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) == 0 - && !IsReflectionBlocked(method)) - { - // Ensure that if SomeMethod is considered reflectable, SomeMethod is also reflectable. - // We only need this because there's a file format limitation in the reflection mapping tables that - // requires generic methods to be concrete (i.e. SomeMethod<__Canon> can never be in the mapping table). - // If we ever lift this limitation, this code can be deleted: the reflectability is going to be covered - // by GetConditionalDependenciesDueToMethodCodePresence below (we get that callback for SomeMethod<__Canon>). - MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); - - dependencies ??= new CombinedDependencyList(); - dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( - factory.ReflectedMethod(method), factory.ReflectedMethod(typicalMethod), "Reflectability of methods is same across genericness")); - } - } - public override void GetConditionalDependenciesDueToMethodCodePresence(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc method) { MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); @@ -711,15 +688,6 @@ public override DependencyList GetDependenciesForCustomAttribute(NodeFactory fac return null; } - public override void GetDependenciesForGenericDictionary(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) - { - // Presence of code might trigger the reflectability dependencies. - if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) != 0) - { - GetDependenciesDueToReflectability(ref dependencies, factory, method); - } - } - public bool GeneratesAttributeMetadata(TypeDesc attributeType) { var ecmaType = attributeType.GetTypeDefinition() as EcmaType; diff --git a/src/libraries/System.Linq/tests/default.rd.xml b/src/libraries/System.Linq/tests/default.rd.xml index 642dbd8db0592..bfe5ecfd159ed 100644 --- a/src/libraries/System.Linq/tests/default.rd.xml +++ b/src/libraries/System.Linq/tests/default.rd.xml @@ -49,6 +49,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -100,6 +140,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +