Skip to content

Commit f37ff8a

Browse files
Make it possible to order methods by specifying symbolic names (#117537)
Text file with an ordered list of symbol names is much easier to emit based on sampling than MIBC (that requires methods in IL terms). Methods that are listed are generated in the specified order. Methods that are not listed are sorted by the compiler. Things that are listed but don't exist are silently skipped.
1 parent 901395a commit f37ff8a

File tree

10 files changed

+105
-6
lines changed

10 files changed

+105
-6
lines changed

src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ The .NET Foundation licenses this file to you under the MIT license.
303303
<IlcArg Condition="'$(TrimmerDefaultAction)' == 'copyused' or '$(TrimmerDefaultAction)' == 'copy' or '$(TrimMode)' == 'partial'" Include="--defaultrooting" />
304304
<IlcArg Condition="$(IlcResilient) != 'false'" Include="--resilient" />
305305
<IlcArg Include="@(UnmanagedEntryPointsAssembly->'--generateunmanagedentrypoints:%(Identity)')" />
306+
<IlcArg Condition="$(IlcOrderFile) != ''" Include="--order:$(IlcOrderFile)" />
307+
<IlcArg Condition="$(IlcOrderFile) != ''" Include="--method-layout:explicit" />
306308

307309
<!-- The managed debugging support in libraries is unused - trim it -->
308310
<IlcArg Condition="'$(DebuggerSupport)' != 'true'" Include="--feature:System.Diagnostics.Debugger.IsSupported=false" />
@@ -322,7 +324,7 @@ The .NET Foundation licenses this file to you under the MIT license.
322324
</Target>
323325

324326
<Target Name="IlcCompile"
325-
Inputs="@(IlcCompileInput);@(IlcReference);@(IlcSatelliteAssembly);@(RdXmlFile);%(ManagedBinary.IlcRspFile)"
327+
Inputs="@(IlcCompileInput);@(IlcReference);@(IlcSatelliteAssembly);@(RdXmlFile);$(IlcOrderFile);%(ManagedBinary.IlcRspFile)"
326328
Outputs="%(ManagedBinary.IlcOutputFile)"
327329
DependsOnTargets="WriteIlcRspFileForCompilation;$(IlcCompileDependsOn)">
328330
<Message Text="Generating native code" Importance="high" />

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/FileLayoutOptimizer.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Diagnostics;
7+
using System.IO;
78

89
using Internal.TypeSystem;
910

@@ -36,6 +37,7 @@ public enum MethodLayoutAlgorithm
3637
#endif
3738
PettisHansen,
3839
Random,
40+
Explicit,
3941
}
4042

4143
public enum FileLayoutAlgorithm
@@ -50,20 +52,23 @@ public FileLayoutOptimizer (Logger logger,
5052
MethodLayoutAlgorithm methodAlgorithm,
5153
FileLayoutAlgorithm fileAlgorithm,
5254
ProfileDataManager profileData,
53-
NodeFactory nodeFactory)
55+
NodeFactory nodeFactory,
56+
string orderFile = null)
5457
{
5558
_logger = logger;
5659
_methodLayoutAlgorithm = methodAlgorithm;
5760
_fileLayoutAlgorithm = fileAlgorithm;
5861
_profileData = profileData;
5962
_nodeFactory = nodeFactory;
63+
_orderFile = orderFile;
6064
}
6165

6266
private Logger _logger;
6367
private MethodLayoutAlgorithm _methodLayoutAlgorithm = MethodLayoutAlgorithm.DefaultSort;
6468
private FileLayoutAlgorithm _fileLayoutAlgorithm = FileLayoutAlgorithm.DefaultSort;
6569
private ProfileDataManager _profileData;
6670
private NodeFactory _nodeFactory;
71+
private string _orderFile;
6772

6873
public ImmutableArray<DependencyNodeCore<NodeFactory>> ApplyProfilerGuidedMethodSort(ImmutableArray<DependencyNodeCore<NodeFactory>> nodes)
6974
{
@@ -200,6 +205,33 @@ int ComputeHotWarmColdRegion(MethodWithGCInfo method)
200205
}
201206
break;
202207

208+
case MethodLayoutAlgorithm.Explicit:
209+
var nameMap = new Dictionary<string, MethodWithGCInfo>(methods.Count);
210+
var order = new Dictionary<MethodWithGCInfo, int>(methods.Count);
211+
212+
for (int i = 0; i < methods.Count; i++)
213+
{
214+
nameMap[methods[i].GetMangledName(_nodeFactory.NameMangler)] = methods[i];
215+
order[methods[i]] = int.MaxValue;
216+
}
217+
218+
using (StreamReader sr = new StreamReader(_orderFile))
219+
{
220+
int line = 0;
221+
while (!sr.EndOfStream)
222+
{
223+
string symbolName = sr.ReadLine();
224+
if (string.IsNullOrEmpty(symbolName)
225+
|| !nameMap.TryGetValue(symbolName, out MethodWithGCInfo m))
226+
continue;
227+
228+
order[m] = line++;
229+
}
230+
}
231+
232+
methods.MergeSortAllowDuplicates((MethodWithGCInfo left, MethodWithGCInfo right) => order[left].CompareTo(order[right]));
233+
break;
234+
203235
default:
204236
throw new NotImplementedException(_methodLayoutAlgorithm.ToString());
205237
}

src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ internal RyuJitCompilation(
4747
RyuJitCompilationOptions options,
4848
MethodLayoutAlgorithm methodLayoutAlgorithm,
4949
FileLayoutAlgorithm fileLayoutAlgorithm,
50-
int parallelism)
50+
int parallelism,
51+
string orderFile)
5152
: base(dependencyGraph, nodeFactory, roots, ilProvider, debugInformationProvider, inliningPolicy, logger)
5253
{
5354
_compilationOptions = options;
@@ -61,7 +62,7 @@ internal RyuJitCompilation(
6162

6263
_parallelism = parallelism;
6364

64-
_fileLayoutOptimizer = new FileLayoutOptimizer(logger, methodLayoutAlgorithm, fileLayoutAlgorithm, profileDataManager, nodeFactory);
65+
_fileLayoutOptimizer = new FileLayoutOptimizer(logger, methodLayoutAlgorithm, fileLayoutAlgorithm, profileDataManager, nodeFactory, orderFile);
6566
}
6667

6768
public ProfileDataManager ProfileData => _profileDataManager;

src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public sealed class RyuJitCompilationBuilder : CompilationBuilder
2121
private FileLayoutAlgorithm _fileLayoutAlgorithm;
2222
private ILProvider _ilProvider = new NativeAotILProvider();
2323
private ProfileDataManager _profileDataManager;
24+
private string _orderFile;
2425
private string _jitPath;
2526

2627
public RyuJitCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group)
@@ -35,6 +36,12 @@ public RyuJitCompilationBuilder UseProfileData(IEnumerable<string> mibcFiles)
3536
return this;
3637
}
3738

39+
public RyuJitCompilationBuilder UseSymbolOrder(string filePath)
40+
{
41+
_orderFile = filePath;
42+
return this;
43+
}
44+
3845
public RyuJitCompilationBuilder UseJitPath(string jitPath)
3946
{
4047
_jitPath = jitPath;
@@ -149,7 +156,8 @@ public override ICompilation ToCompilation()
149156
options,
150157
_methodLayoutAlgorithm,
151158
_fileLayoutAlgorithm,
152-
_parallelism);
159+
_parallelism,
160+
_orderFile);
153161
}
154162
}
155163
}

src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ internal sealed class ILCompilerRootCommand : RootCommand
3131
new("--method-layout") { CustomParser = MakeMethodLayoutAlgorithm, DefaultValueFactory = MakeMethodLayoutAlgorithm, Description = "Layout algorithm used by profile-driven optimization for arranging methods in a file.", HelpName = "arg" };
3232
public Option<FileLayoutAlgorithm> FileLayout { get; } =
3333
new("--file-layout") { CustomParser = MakeFileLayoutAlgorithm, DefaultValueFactory = MakeFileLayoutAlgorithm, Description = "Layout algorithm used by profile-driven optimization for arranging non-method contents in a file.", HelpName = "arg" };
34+
public Option<string> OrderFile { get; } =
35+
new("--order") { Description = "File that specifies order of symbols within the generated object file" };
3436
public Option<string[]> SatelliteFilePaths { get; } =
3537
new("--satellite") { DefaultValueFactory = _ => Array.Empty<string>(), Description = "Satellite assemblies associated with inputs/references" };
3638
public Option<bool> EnableDebugInfo { get; } =
@@ -193,6 +195,7 @@ public ILCompilerRootCommand(string[] args) : base(".NET Native IL Compiler")
193195
Options.Add(MibcFilePaths);
194196
Options.Add(MethodLayout);
195197
Options.Add(FileLayout);
198+
Options.Add(OrderFile);
196199
Options.Add(SatelliteFilePaths);
197200
Options.Add(EnableDebugInfo);
198201
Options.Add(UseDwarf5);
@@ -300,7 +303,7 @@ public ILCompilerRootCommand(string[] args) : base(".NET Native IL Compiler")
300303

301304
#pragma warning disable CA1861 // Avoid constant arrays as arguments. Only executed once during the execution of the program.
302305
Helpers.MakeReproPackage(makeReproPath, result.GetValue(OutputFilePath), args, result,
303-
inputOptions : new[] { "-r", "--reference", "-m", "--mibc", "--rdxml", "--directpinvokelist", "--descriptor", "--satellite" },
306+
inputOptions : new[] { "-r", "--reference", "-m", "--mibc", "--rdxml", "--directpinvokelist", "--descriptor", "--satellite", "--order" },
304307
outputOptions : new[] { "-o", "--out", "--exportsfile", "--dgmllog", "--scandgmllog", "--mstat", "--sourcelink" });
305308
#pragma warning restore CA1861 // Avoid constant arrays as arguments
306309
}
@@ -424,6 +427,7 @@ private static MethodLayoutAlgorithm MakeMethodLayoutAlgorithm(ArgumentResult re
424427
"hotwarmcold" => MethodLayoutAlgorithm.HotWarmCold,
425428
"pettishansen" => MethodLayoutAlgorithm.PettisHansen,
426429
"random" => MethodLayoutAlgorithm.Random,
430+
"explicit" => MethodLayoutAlgorithm.Explicit,
427431
_ => throw new CommandLineException(result.Tokens[0].Value)
428432
};
429433
}

src/coreclr/tools/aot/ILCompiler/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ public int Run()
361361
string compilationUnitPrefix = multiFile ? Path.GetFileNameWithoutExtension(outputFilePath) : "";
362362
var builder = new RyuJitCompilationBuilder(typeSystemContext, compilationGroup)
363363
.FileLayoutAlgorithms(Get(_command.MethodLayout), Get(_command.FileLayout))
364+
.UseSymbolOrder(Get(_command.OrderFile))
364365
.UseCompilationUnitPrefix(compilationUnitPrefix);
365366

366367
string[] mibcFilePaths = Get(_command.MibcFilePaths);

src/tests/nativeaot/SmokeTests/UnitTests/Main.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
success &= RunTest(Threading.Run);
1212
success &= RunTest(Devirtualization.Run);
1313
success &= RunTest(StackTraces.Run);
14+
success &= RunTest(Ordering.Run);
1415

1516
return success ? 100 : 1;
1617

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
6+
class Ordering
7+
{
8+
internal static unsafe int Run()
9+
{
10+
// Method addresses are not observable in WASM
11+
if (OperatingSystem.IsWasi() || OperatingSystem.IsBrowser())
12+
return 100;
13+
14+
var keys = new nint[]
15+
{
16+
(nint)(delegate*<Guid>)&Method4,
17+
(nint)(delegate*<Guid>)&Method3,
18+
(nint)(delegate*<Guid>)&Method2,
19+
(nint)(delegate*<Guid>)&Method1,
20+
(nint)(delegate*<Guid>)&Method0,
21+
};
22+
23+
var items = new int[] { 4, 3, 2, 1, 0 };
24+
25+
Array.Sort(keys, items);
26+
27+
// the order specified in the order.txt file
28+
var expectedOrder = new int[] { 2, 1, 3, 0, 4 };
29+
30+
for (int i = 0; i < items.Length; i++)
31+
if (items[i] != expectedOrder[i])
32+
throw new Exception(i.ToString());
33+
34+
return 100;
35+
}
36+
37+
static Guid Method0() => new Guid(0xb20e3a5f, 0x4aad, 0x4225, 0x98, 0x26, 0xac, 0xe8, 0xe0, 0xf7, 0x64, 0x56);
38+
static Guid Method1() => new Guid(0x13464316, 0xb19c, 0x4e1c, 0x95, 0x2e, 0x22, 0xb4, 0xa, 0x21, 0x7d, 0xd5);
39+
static Guid Method2() => new Guid(0x510f2c1e, 0x7715, 0x4aee, 0x8d, 0xd5, 0x16, 0xf8, 0xd5, 0x70, 0x5, 0x90);
40+
static Guid Method3() => new Guid(0x4cc6e597, 0x875e, 0x4cb0, 0x90, 0x88, 0xcb, 0x4e, 0xd8, 0x8, 0x91, 0xb8);
41+
static Guid Method4() => new Guid(0x2d2e2b87, 0x75f5, 0x4c16, 0x93, 0xa9, 0xbe, 0xbd, 0x6b, 0x58, 0xbd, 0xd6);
42+
}

src/tests/nativeaot/SmokeTests/UnitTests/UnitTests.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@
1010

1111
<RequiresProcessIsolation>true</RequiresProcessIsolation>
1212
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>
13+
14+
<IlcOrderFile>order.txt</IlcOrderFile>
1315
</PropertyGroup>
1416
<ItemGroup>
1517
<Compile Include="BasicThreading.cs" />
1618
<Compile Include="Delegates.cs" />
1719
<Compile Include="Devirtualization.cs" />
1820
<Compile Include="Generics.cs" />
1921
<Compile Include="Interfaces.cs" />
22+
<Compile Include="Ordering.cs" />
2023
<Compile Include="Threading.cs" />
2124
<Compile Include="StackTraces.cs" />
2225
<Compile Include="Main.cs" />
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
UnitTests_Ordering__Method2
2+
UnitTests_Ordering__Method1
3+
UnitTests_Ordering__Method3
4+
UnitTests_Ordering__Method0
5+
UnitTests_Ordering__Method4

0 commit comments

Comments
 (0)