From baf9403dc1f221d7299e8f9cfecf002a2b0fce63 Mon Sep 17 00:00:00 2001 From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> Date: Tue, 29 Nov 2022 11:00:17 -0600 Subject: [PATCH] Call CheckProcessed before enqueuing to MarkStep._methods (dotnet/linker#3139) * Call CheckProcessed before enqueuing to MarkStep._methods to avoid redundantly adding methods Commit migrated from https://github.com/dotnet/linker/commit/261e91198bc9ec29f6904eff764cb65a25bd76ac --- .../src/linker/Linker.Steps/MarkStep.cs | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs index 7d06799de40a..735bf7641e3e 100644 --- a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs @@ -2929,12 +2929,38 @@ protected internal void MarkIndirectlyCalledMethod (MethodDefinition method, in if (Annotations.GetAction (method) == MethodAction.Nothing) Annotations.SetAction (method, MethodAction.Parse); - EnqueueMethod (method, reason, origin); // Use the original reason as it's important to correctly generate warnings // the updated reason is only useful for better tracking of dependencies. ProcessAnalysisAnnotationsForMethod (method, originalReasonKind, origin); + // Record the reason for marking a method on each call. + switch (reason.Kind) { + case DependencyKind.AlreadyMarked: + Debug.Assert (Annotations.IsMarked (method)); + break; + default: + Annotations.Mark (method, reason, origin); + break; + } + + bool markedForCall = + reason.Kind == DependencyKind.DirectCall || + reason.Kind == DependencyKind.VirtualCall || + reason.Kind == DependencyKind.Newobj; + if (markedForCall) { + // Record declaring type of a called method up-front as a special case so that we may + // track at least some method calls that trigger a cctor. + // Temporarily switch to the original source for marking this method + // this is for the same reason as for tracking, but this time so that we report potential + // warnings from a better place. + MarkType (method.DeclaringType, new DependencyInfo (DependencyKind.DeclaringTypeOfCalledMethod, method), new MessageOrigin (reason.Source as IMemberDefinition ?? method)); + } + + // We will only enqueue a method to be processed if it hasn't been processed yet. + if (!CheckProcessed (method)) + EnqueueMethod (method, reason, origin); + return method; } @@ -3113,32 +3139,10 @@ protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo using var parentScope = ScopeStack.PushScope (new MarkScopeStack.Scope (origin)); using var methodScope = ScopeStack.PushScope (new MessageOrigin (method)); - // Record the reason for marking a method on each call. The logic under CheckProcessed happens - // only once per method. - switch (reason.Kind) { - case DependencyKind.AlreadyMarked: - Debug.Assert (Annotations.IsMarked (method)); - break; - default: - Annotations.Mark (method, reason, ScopeStack.CurrentScope.Origin); - break; - } - bool markedForCall = reason.Kind == DependencyKind.DirectCall || reason.Kind == DependencyKind.VirtualCall || reason.Kind == DependencyKind.Newobj; - if (markedForCall) { - // Record declaring type of a called method up-front as a special case so that we may - // track at least some method calls that trigger a cctor. - // Temporarily switch to the original source for marking this method - // this is for the same reason as for tracking, but this time so that we report potential - // warnings from a better place. - MarkType (method.DeclaringType, new DependencyInfo (DependencyKind.DeclaringTypeOfCalledMethod, method), new MessageOrigin (reason.Source as IMemberDefinition ?? method)); - } - - if (CheckProcessed (method)) - return; foreach (Action handleMarkMethod in MarkContext.MarkMethodActions) handleMarkMethod (method);