Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Boemer <sbomer@gmail.com>2020-03-27 10:44:24 +0300
committerGitHub <noreply@github.com>2020-03-27 10:44:24 +0300
commit83a48f3ca59d9587669712291119ef730a6551d4 (patch)
tree55e52704dee9ec5300c5b9eae539ad93f9a3f17c /src/linker/Linker/XmlDependencyRecorder.cs
parent42b986633a3b78ea547a3f4ac36c259ff05566c2 (diff)
Add tracing reasons (#1012)
* Add tracing reasons This supplies a "reason" every time that we mark a piece of IL. A "reason" is an instance of a new type, DependencyInfo, which tracks a single source object and a flag (DependencyKind) indicating what kind of dependency this is. Annotations.Mark now expects a DependencyInfo, and the dependency reporting interface is extended to report these reasons. The mark sites within MarkStep and other steps have been updated with specific reasons, and the corresponding Mark* methods have been modified to take a reason that is passed through as many layers of the marking logic as necessary until it reaches a call to Annotations.Mark. The marking logic has been modified to more frequently allow marking Cecil objects multiple times for different reasons - while still ensuring that any expensive operations are done only once per object (usually under an IsProcessed check, rather than an IsMarked check). In a few cases, the marking logic will process a Cecil object and mark its dependencies, without marking the original Cecil object. This can happen, for example, for custom attributes in some cases, or for generic instantiations (since we only mark definitions). In these cases, there are extra calls that report these intermediate dependencies to the tracing interface without actually marking them. Some of the DependencyKinds (for example AlreadyMarked) are only used for internal tracking, and will not be reported to the dependency tracing interface. The set of DependencyKinds has been selected based on what seems like an intuitive reason to report for each object, though sometimes the choice is not obvious since the reasons are restricted to supplying a single source object. Some interesting cases where potentially non-obvious choices were made follow: - When marking overrides on instantiated type, we choose as the reason the instantiated type, rather than the base method (unless the override removal optimization is disabled, in which case instantiations are not taken into account when marking overrides - so we blame the base method). - When marking static constructors, we keep track of cases where they are marked due to a field access or method call from another method, and report these separately. For cases where we track enough information to do so, this results in a more direct dependency chain like: "method A triggers static constructor B", rather than "method A access field B, field B has declaring type C, declaring type C has static constructor D". - When marking custom attributes on assemblies or modules, we record a dependency from the assembly/module to the attribute, even though the assembly/module may not have been marked or even recorded. Since the attributes and their dependencies are kept regardless of what happens to the assembly, these are conceptually entry points to the analysis. This also includes a change that moves the reflection reporter from LinkContext to Tracer, and extended to support multiple sinks, similar to the dependency reporting. I have also added assertions in a few places where I think it makes sense to check invariants when we are running tests in Debug mode. * Make DependencyKind arrays static, add more comments * Number the DependencyKind enum * Pass DependencyInfo as in parameter where it makes sense The methods that reuse the "reason" variable were not modified. * Use static fields for well-known DependencyInfo without source Instead of a ctor that just sets the source to null. * Undo ReflectionPatternRecorder changes Move the reflection pattern recorder back to LinkContext * Remove stack-based dependency recording * Add DependencyKind.Custom * Workaround for ReducedTracing * Use -1 for DependencyKind.Custom * Add back obsolete Mark method for monolinker build
Diffstat (limited to 'src/linker/Linker/XmlDependencyRecorder.cs')
-rw-r--r--src/linker/Linker/XmlDependencyRecorder.cs24
1 files changed, 14 insertions, 10 deletions
diff --git a/src/linker/Linker/XmlDependencyRecorder.cs b/src/linker/Linker/XmlDependencyRecorder.cs
index 637b94c2a..8f093a29c 100644
--- a/src/linker/Linker/XmlDependencyRecorder.cs
+++ b/src/linker/Linker/XmlDependencyRecorder.cs
@@ -89,23 +89,27 @@ namespace Mono.Linker
stream = null;
}
+ public void RecordDependency (object target, in DependencyInfo reason, bool marked)
+ {
+ // For now, just report a dependency from source to target without noting the DependencyKind.
+ RecordDependency (reason.Source, target, marked);
+ }
+
public void RecordDependency (object source, object target, bool marked)
{
if (!ShouldRecord (source) && !ShouldRecord (target))
return;
- // This is a hack to work around a quirk of MarkStep that results in outputting ~6k edges even with the above ShouldRecord checks.
- // What happens is that due to the method queueing in MarkStep, the dependency chain is broken in many cases. And in these cases
- // we end up adding an edge for MarkStep -> <queued Method>
- // This isn't particularly useful information since it's incomplete, but it's especially not useful in ReducedTracing mode when there is one of these for
- // every class library method that was queued.
- if (context.EnableReducedTracing && source is MarkStep && !ShouldRecord (target))
+ // We use a few hacks to work around MarkStep outputting thousands of edges even
+ // with the above ShouldRecord checks. Ideally we would format these into a meaningful format
+ // however I don't think that is worth the effort at the moment.
+
+ // Prevent useless logging of attributes like `e="Other:Mono.Cecil.CustomAttribute"`.
+ if (source is CustomAttribute || target is CustomAttribute)
return;
- // This is another hack to prevent useless information from being logged. With the introduction of interface sweeping there are a lot of edges such as
- // `e="InterfaceImpl:Mono.Cecil.InterfaceImplementation"` which are useless information. Ideally we would format the interface implementation into a meaningful format
- // however I don't think that is worth the effort at the moment.
- if (target is InterfaceImplementation)
+ // Prevent useless logging of interface implementations like `e="InterfaceImpl:Mono.Cecil.InterfaceImplementation"`.
+ if (source is InterfaceImplementation || target is InterfaceImplementation)
return;
if (source != target) {