-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Inline resource strings in the compiler (#80896)
On a high level: * When we're looking at IL to do substitutions, we additionally look for calls to `SR.SomeResourceName`. These are generated properties (generated by a piece of code in Arcade) that basically just do `GetResourceString(nameof(SomeResourceName))`. We look up what the resource string is (in the manifest resource) and replace the call with the looked up string literal. * We also keep track of calls to `SR.GetResourceString`. Seeing this in the graph means that the optimization was defeated - someone bypassed the generated accessors. If we see one, we add dependency graph node to the graph that represent the manifest resource that has the string. * When generating managed resources we skip over the one that has the strings unless the above dependency node is in the graph. This allows optimizing away the resource blobs if all accesses were inlined.
- Loading branch information
1 parent
b6935d3
commit 759fecb
Showing
11 changed files
with
257 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
...ools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InlineableStringsResourceNode.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
|
||
using ILCompiler.DependencyAnalysisFramework; | ||
using Internal.TypeSystem; | ||
using Internal.TypeSystem.Ecma; | ||
|
||
namespace ILCompiler.DependencyAnalysis | ||
{ | ||
/// <summary> | ||
/// Represents a resource blob used by the SR class in the BCL. | ||
/// If this node is present in the graph, it means we were not able to optimize its use away | ||
/// and the blob has to be generated. | ||
/// </summary> | ||
internal sealed class InlineableStringsResourceNode : DependencyNodeCore<NodeFactory> | ||
{ | ||
private readonly EcmaModule _module; | ||
|
||
public const string ResourceAccessorTypeName = "SR"; | ||
public const string ResourceAccessorTypeNamespace = "System"; | ||
public const string ResourceAccessorGetStringMethodName = "GetResourceString"; | ||
|
||
public InlineableStringsResourceNode(EcmaModule module) | ||
{ | ||
_module = module; | ||
} | ||
|
||
public override bool InterestingForDynamicDependencyAnalysis => false; | ||
|
||
public override bool HasDynamicDependencies => false; | ||
|
||
public override bool HasConditionalStaticDependencies => false; | ||
|
||
public override bool StaticDependenciesAreComputed => true; | ||
|
||
public static bool IsInlineableStringsResource(EcmaModule module, string resourceName) | ||
{ | ||
if (!resourceName.EndsWith(".resources", StringComparison.Ordinal)) | ||
return false; | ||
|
||
// Make a guess at the name of the resource Arcade tooling generated for the resource | ||
// strings. | ||
// https://github.com/dotnet/runtime/issues/81385 tracks not having to guess this. | ||
string simpleName = module.Assembly.GetName().Name; | ||
string resourceName1 = $"{simpleName}.Strings.resources"; | ||
string resourceName2 = $"FxResources.{simpleName}.SR.resources"; | ||
|
||
if (resourceName != resourceName1 && resourceName != resourceName2) | ||
return false; | ||
|
||
MetadataType srType = module.GetType(ResourceAccessorTypeNamespace, ResourceAccessorTypeName, throwIfNotFound: false); | ||
if (srType == null) | ||
return false; | ||
|
||
return srType.GetMethod(ResourceAccessorGetStringMethodName, null) != null; | ||
} | ||
|
||
public static void AddDependenciesDueToResourceStringUse(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) | ||
{ | ||
if (method.Name == ResourceAccessorGetStringMethodName && method.OwningType is MetadataType mdType | ||
&& mdType.Name == ResourceAccessorTypeName && mdType.Namespace == ResourceAccessorTypeNamespace) | ||
{ | ||
dependencies ??= new DependencyList(); | ||
dependencies.Add(factory.InlineableStringResource((EcmaModule)mdType.Module), "Using the System.SR class"); | ||
} | ||
} | ||
|
||
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) => null; | ||
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context) => null; | ||
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null; | ||
protected override string GetName(NodeFactory context) | ||
=> $"String resources for {_module.Assembly.GetName().Name}"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.