-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Linker dependency framework #101277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Linker dependency framework #101277
Changes from 19 commits
afe8990
4a92aaf
76fe923
b3ccd66
eb5e333
e1270bb
2d12ade
1dc80db
991f7a0
069f47b
c1670eb
8382e68
5bf5ece
e6edbce
10a5c57
166d2d5
01f3a79
098f7bc
25ec8ce
9ef1343
d50d70c
dfe51f2
afedfb7
a600348
8d642a5
a0ea640
2bb99d7
b27bc04
3394758
1abe4b3
8cbedd1
df7a522
28bf0be
3ca9f9a
830f23e
3001124
f003f74
a0f6861
d358b42
0fab4e3
5e124b5
855b109
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright (c) .NET Foundation and contributors. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using Mono.Cecil; | ||
|
||
namespace Mono.Linker.Steps | ||
{ | ||
public partial class MarkStep | ||
{ | ||
internal sealed class MarkStepNodeFactory (MarkStep markStep) | ||
{ | ||
public MarkStep MarkStep { get; } = markStep; | ||
readonly NodeCache<TypeDefinition, TypeDefinitionDependencyNode> _typeNodes = new (static _ => throw new InvalidOperationException ("Creation of node requires more than the key.")); | ||
readonly NodeCache<MethodDefinition, MethodDefinitionDependencyNode> _methodNodes = new (static _ => throw new InvalidOperationException ("Creation of node requires more than the key.")); | ||
readonly NodeCache<TypeDefinition, TypeIsRelevantToVariantCastingNode> _typeIsRelevantToVariantCastingNodes = new (static (t) => new TypeIsRelevantToVariantCastingNode (t)); | ||
|
||
internal TypeDefinitionDependencyNode GetTypeNode (TypeDefinition reference, DependencyInfo reason, MessageOrigin? origin) | ||
{ | ||
return _typeNodes.GetOrAdd (reference, (k) => new TypeDefinitionDependencyNode (k, reason, origin)); | ||
} | ||
|
||
internal MethodDefinitionDependencyNode GetMethodDefinitionNode (MethodDefinition method, DependencyInfo reason, MessageOrigin origin) | ||
{ | ||
return _methodNodes.GetOrAdd (method, (k) => new MethodDefinitionDependencyNode (k, reason, origin)); | ||
} | ||
|
||
internal TypeIsRelevantToVariantCastingNode GetTypeIsRelevantToVariantCastingNode (TypeDefinition type) | ||
{ | ||
return _typeIsRelevantToVariantCastingNodes.GetOrAdd (type); | ||
} | ||
|
||
struct NodeCache<TKey, TValue> where TKey : notnull | ||
{ | ||
// Change to concurrent dictionary if/when multithreaded marking is enabled | ||
readonly Dictionary<TKey, TValue> _cache; | ||
readonly Func<TKey, TValue> _creator; | ||
|
||
public NodeCache (Func<TKey, TValue> creator, IEqualityComparer<TKey> comparer) | ||
{ | ||
_creator = creator; | ||
_cache = new (comparer); | ||
} | ||
|
||
public NodeCache (Func<TKey, TValue> creator) | ||
{ | ||
_creator = creator; | ||
_cache = new (); | ||
} | ||
|
||
public TValue GetOrAdd (TKey key) | ||
{ | ||
return _cache.GetOrAdd (key, _creator); | ||
} | ||
|
||
public TValue GetOrAdd (TKey key, Func<TKey, TValue> creator) | ||
{ | ||
return _cache.GetOrAdd (key, creator); | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Copyright (c) .NET Foundation and contributors. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using ILCompiler.DependencyAnalysisFramework; | ||
using Mono.Cecil; | ||
|
||
namespace Mono.Linker.Steps | ||
{ | ||
public partial class MarkStep | ||
{ | ||
internal sealed class MethodDefinitionDependencyNode : DependencyNodeCore<MarkStepNodeFactory> | ||
jtschuster marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
readonly MethodDefinition method; | ||
readonly MessageOrigin origin; | ||
readonly DependencyInfo reason; | ||
jtschuster marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
public MethodDefinitionDependencyNode (MethodDefinition method, DependencyInfo reason, MessageOrigin origin) | ||
{ | ||
this.method = method; | ||
this.origin = origin; | ||
this.reason = reason; | ||
} | ||
|
||
public override bool InterestingForDynamicDependencyAnalysis => false; | ||
|
||
public override bool HasDynamicDependencies => false; | ||
|
||
public override bool HasConditionalStaticDependencies => false; | ||
|
||
public override bool StaticDependenciesAreComputed => true; | ||
|
||
public override IEnumerable<DependencyListEntry>? GetStaticDependencies (MarkStepNodeFactory context) | ||
{ | ||
context.MarkStep.ProcessMethod (method, reason, origin); | ||
return null; | ||
} | ||
|
||
public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (MarkStepNodeFactory context) => null; | ||
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<MarkStepNodeFactory>> markedNodes, int firstNode, MarkStepNodeFactory context) => null; | ||
protected override string GetName (MarkStepNodeFactory context) => "MethodDefinition"; | ||
jtschuster marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright (c) .NET Foundation and contributors. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using ILCompiler.DependencyAnalysisFramework; | ||
|
||
namespace Mono.Linker.Steps | ||
{ | ||
|
||
public partial class MarkStep | ||
{ | ||
sealed class ProcessCallbackDependencyNode : DependencyNodeCore<MarkStepNodeFactory> | ||
{ | ||
Func<bool> _processAction; | ||
DependencyList? _dependencies; | ||
|
||
public ProcessCallbackDependencyNode (Func<bool> action) => _processAction = action; | ||
|
||
public void Process () | ||
{ | ||
_dependencies = new DependencyList (); | ||
if (_processAction ()) { | ||
_dependencies.Add (new ProcessCallbackDependencyNode (_processAction), "Some processing was done, continuation required"); | ||
} | ||
} | ||
|
||
public override bool InterestingForDynamicDependencyAnalysis => false; | ||
|
||
public override bool HasDynamicDependencies => false; | ||
|
||
public override bool HasConditionalStaticDependencies => false; | ||
|
||
public override bool StaticDependenciesAreComputed => _dependencies != null; | ||
|
||
public override IEnumerable<DependencyListEntry>? GetStaticDependencies (MarkStepNodeFactory context) => _dependencies; | ||
|
||
public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (MarkStepNodeFactory context) => null; | ||
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<MarkStepNodeFactory>> markedNodes, int firstNode, MarkStepNodeFactory context) => null; | ||
protected override string GetName (MarkStepNodeFactory context) => "Process"; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Copyright (c) .NET Foundation and contributors. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System.Collections.Generic; | ||
using ILCompiler.DependencyAnalysisFramework; | ||
using Mono.Cecil; | ||
|
||
namespace Mono.Linker.Steps | ||
{ | ||
|
||
public partial class MarkStep | ||
{ | ||
internal sealed class TypeDefinitionDependencyNode : DependencyNodeCore<MarkStepNodeFactory> | ||
{ | ||
readonly TypeDefinition type; | ||
readonly MessageOrigin? origin; | ||
readonly DependencyInfo reason; | ||
|
||
public TypeDefinitionDependencyNode (TypeDefinition type, DependencyInfo reason, MessageOrigin? origin) | ||
{ | ||
this.type = type; | ||
this.origin = origin; | ||
this.reason = reason; | ||
} | ||
|
||
public override bool InterestingForDynamicDependencyAnalysis => false; | ||
|
||
public override bool HasDynamicDependencies => false; | ||
|
||
public override bool HasConditionalStaticDependencies => false; | ||
|
||
public override bool StaticDependenciesAreComputed => true; | ||
|
||
public override IEnumerable<DependencyListEntry>? GetStaticDependencies (MarkStepNodeFactory context) | ||
{ | ||
yield break; | ||
} | ||
|
||
public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (MarkStepNodeFactory context) => null; | ||
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<MarkStepNodeFactory>> markedNodes, int firstNode, MarkStepNodeFactory context) => null; | ||
protected override string GetName (MarkStepNodeFactory context) => "TypeNode"; | ||
protected override void OnMarked (MarkStepNodeFactory context) | ||
{ | ||
using MarkScopeStack.LocalScope? localScope = origin.HasValue ? context.MarkStep.ScopeStack.PushLocalScope (origin.Value) : null; | ||
context.MarkStep.ProcessType (type, reason, origin); | ||
jtschuster marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Copyright (c) .NET Foundation and contributors. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System.Collections.Generic; | ||
using ILCompiler.DependencyAnalysisFramework; | ||
using Mono.Cecil; | ||
|
||
namespace Mono.Linker.Steps | ||
{ | ||
|
||
jtschuster marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public partial class MarkStep | ||
{ | ||
internal sealed class TypeIsRelevantToVariantCastingNode : DependencyNodeCore<MarkStepNodeFactory> | ||
{ | ||
TypeDefinition type; | ||
public TypeIsRelevantToVariantCastingNode (TypeDefinition type) => this.type = type; | ||
|
||
public override bool InterestingForDynamicDependencyAnalysis => false; | ||
|
||
public override bool HasDynamicDependencies => false; | ||
|
||
public override bool HasConditionalStaticDependencies => false; | ||
|
||
public override bool StaticDependenciesAreComputed => true; | ||
|
||
public override IEnumerable<DependencyListEntry>? GetStaticDependencies (MarkStepNodeFactory context) | ||
{ | ||
yield break; | ||
} | ||
|
||
public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (MarkStepNodeFactory context) => null; | ||
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<MarkStepNodeFactory>> markedNodes, int firstNode, MarkStepNodeFactory context) => null; | ||
protected override string GetName (MarkStepNodeFactory context) => "TypeIsRelevantToVariantCasting"; | ||
protected override void OnMarked (MarkStepNodeFactory context) | ||
{ | ||
context.MarkStep.Annotations.MarkRelevantToVariantCasting (type); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When do we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just used OnMarked arbitrarily for this since there aren't any dependencies. It looks like OnMarked will do work up front when the node is returned from another GetStaticDependencies, then it's added to a stack to later call GetStaticDependencies. |
||
} | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.