diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs index 02fd1412caf845..e56d1c5d5142fb 100644 --- a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs @@ -60,7 +60,7 @@ protected LinkContext Context { } protected Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> _methods; - protected HashSet<(MethodDefinition, MarkScopeStack.Scope)> _virtual_methods; + protected Dictionary _virtual_methods; protected Queue _assemblyLevelAttributes; readonly List _ivt_attributes; protected Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> _lateMarkedAttributes; @@ -220,7 +220,7 @@ internal DynamicallyAccessedMembersTypeHierarchy DynamicallyAccessedMembersTypeH public MarkStep () { _methods = new Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> (); - _virtual_methods = new HashSet<(MethodDefinition, MarkScopeStack.Scope)> (); + _virtual_methods = new Dictionary (); _assemblyLevelAttributes = new Queue (); _ivt_attributes = new List (); _lateMarkedAttributes = new Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> (); @@ -588,10 +588,8 @@ void ProcessMarkedTypesWithInterfaces () // We may mark an interface type later on. Which means we need to reprocess any time with one or more interface implementations that have not been marked // and if an interface type is found to be marked and implementation is not marked, then we need to mark that implementation - // copy the data to avoid modified while enumerating error potential, which can happen under certain conditions. - var typesWithInterfaces = _typesWithInterfaces.ToArray (); - - foreach ((var type, var scope) in typesWithInterfaces) { + for (int i = 0; i < _typesWithInterfaces.Count; i++) { + (var type, var scope) = _typesWithInterfaces[i]; // Exception, types that have not been flagged as instantiated yet. These types may not need their interfaces even if the // interface type is marked // UnusedInterfaces optimization is turned off mark all interface implementations @@ -609,7 +607,7 @@ void ProcessMarkedTypesWithInterfaces () continue; foreach (var ov in baseMethods) { if (ov.Base.DeclaringType is not null && ov.Base.DeclaringType.IsInterface && IgnoreScope (ov.Base.DeclaringType.Scope)) { - _virtual_methods.Add ((ov.Base, ScopeStack.CurrentScope)); + _virtual_methods.TryAdd (ov.Base, ScopeStack.CurrentScope); } } } @@ -707,9 +705,10 @@ void ProcessVirtualMethod (MethodDefinition method) MarkMethod (dimInfo.Override, new DependencyInfo (DependencyKind.Override, dimInfo.Base), ScopeStack.CurrentScope.Origin); } } - var overridingMethods = Annotations.GetOverrides (method); + List? overridingMethods = (List?)Annotations.GetOverrides (method); if (overridingMethods is not null) { - foreach (OverrideInformation ov in overridingMethods) { + for (int i = 0; i < overridingMethods.Count; i++) { + OverrideInformation ov = overridingMethods[i]; if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (ov)) MarkMethod (ov.Override, new DependencyInfo (DependencyKind.Override, ov.Base), ScopeStack.CurrentScope.Origin); } @@ -3267,7 +3266,7 @@ protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo MarkMethodSpecialCustomAttributes (method); if (method.IsVirtual) - _virtual_methods.Add ((method, ScopeStack.CurrentScope)); + _virtual_methods.TryAdd (method, ScopeStack.CurrentScope); MarkNewCodeDependencies (method); @@ -3475,7 +3474,7 @@ void MarkBaseMethods (MethodDefinition method) // This will produce warnings for all interface methods and virtual methods regardless of whether the interface, interface implementation, or interface method is kept or not. if (ov.Base.DeclaringType.IsInterface && !method.DeclaringType.IsInterface) { // These are all virtual, no need to check IsVirtual before adding to list - _virtual_methods.Add ((ov.Base, ScopeStack.CurrentScope)); + _virtual_methods.TryAdd (ov.Base, ScopeStack.CurrentScope); continue; } diff --git a/src/tools/illink/src/linker/Linker/Annotations.cs b/src/tools/illink/src/linker/Linker/Annotations.cs index a7f77cf0efae90..68c8c320749966 100644 --- a/src/tools/illink/src/linker/Linker/Annotations.cs +++ b/src/tools/illink/src/linker/Linker/Annotations.cs @@ -719,7 +719,7 @@ public void EnqueueVirtualMethod (MethodDefinition method) VirtualMethodsWithAnnotationsToValidate.Add (method); } - internal List<(TypeReference, List)>? GetRecursiveInterfaces (TypeDefinition type) + internal List<(TypeReference InterfaceType, List ImplementationChain)>? GetRecursiveInterfaces (TypeDefinition type) { return TypeMapInfo.GetRecursiveInterfaces (type); } diff --git a/src/tools/illink/src/linker/Linker/TypeMapInfo.cs b/src/tools/illink/src/linker/Linker/TypeMapInfo.cs index d2813c8982c4f0..1d7b24e070d148 100644 --- a/src/tools/illink/src/linker/Linker/TypeMapInfo.cs +++ b/src/tools/illink/src/linker/Linker/TypeMapInfo.cs @@ -66,7 +66,7 @@ public void EnsureProcessed (AssemblyDefinition assembly) /// /// Returns a list of all known methods that override . The list may be incomplete if other overrides exist in assemblies that haven't been processed by TypeMapInfo yet /// - public IEnumerable? GetOverrides (MethodDefinition method) + public List? GetOverrides (MethodDefinition method) { EnsureProcessed (method.Module.Assembly); override_methods.TryGetValue (method, out List? overrides); @@ -130,14 +130,15 @@ protected virtual void MapType (TypeDefinition type) MapType (nested); } - internal List<(TypeReference, List)>? GetRecursiveInterfaces (TypeDefinition type) + internal List<(TypeReference InterfaceType, List ImplementationChain)>? GetRecursiveInterfaces (TypeDefinition type) { + EnsureProcessed(type.Module.Assembly); if (interfaces.TryGetValue (type, out var value)) return value; return null; } - List<(TypeReference, List)> GetRecursiveInterfaceImplementations (TypeDefinition type) + List<(TypeReference InterfaceType, List ImplementationChain)> GetRecursiveInterfaceImplementations (TypeDefinition type) { List<(TypeReference, List)> firstImplementationChain = new ();