From 0c4bf19fa6cf5dc64afd4d998246ef29177bab84 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Wed, 24 May 2023 14:49:08 -0400 Subject: [PATCH 01/27] Add the capability of trimming individual methods --- src/mono/mono/mini/aot-compiler.c | 2 + src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 161 +++++++++++++++--- 2 files changed, 144 insertions(+), 19 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 52147fcbec951..040c37d665bc2 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -14830,6 +14830,8 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) if (acfg->aot_opts.compiled_methods_outfile && acfg->dedup_phase != DEDUP_COLLECT) { acfg->compiled_methods_outfile = fopen (acfg->aot_opts.compiled_methods_outfile, "w+"); + fprintf(acfg->compiled_methods_outfile, "%s\n", ass->aname.name); + if (!acfg->compiled_methods_outfile) aot_printerrf (acfg, "Unable to open compiled-methods-outfile specified file %s\n", acfg->aot_opts.compiled_methods_outfile); } diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 1f80296537177..409e3e1a5648f 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -12,6 +12,9 @@ using CilStrip.Mono.Cecil.Binary; using CilStrip.Mono.Cecil.Cil; using CilStrip.Mono.Cecil.Metadata; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using System.Reflection.PortableExecutable; public class ILStrip : Microsoft.Build.Utilities.Task { @@ -19,7 +22,6 @@ public class ILStrip : Microsoft.Build.Utilities.Task /// Assemblies to be stripped. /// The assemblies will be modified in place if OutputPath metadata is not set. /// - [Required] public ITaskItem[] Assemblies { get; set; } = Array.Empty(); /// @@ -27,30 +29,64 @@ public class ILStrip : Microsoft.Build.Utilities.Task /// public bool DisableParallelStripping { get; set; } + public bool TrimIndividualMethods { get; set; } + + public ITaskItem[] MethodTokenFiles { get; set; } = Array.Empty(); + + public string AssemblyPath { get; set; } = ""; + public override bool Execute() { - if (Assemblies.Length == 0) + if (!TrimIndividualMethods) { - throw new ArgumentException($"'{nameof(Assemblies)}' is required.", nameof(Assemblies)); - } + if (Assemblies.Length == 0) + { + throw new ArgumentException($"'{nameof(Assemblies)}' is required.", nameof(Assemblies)); + } - int allowedParallelism = DisableParallelStripping ? 1 : Math.Min(Assemblies.Length, Environment.ProcessorCount); - if (BuildEngine is IBuildEngine9 be9) - allowedParallelism = be9.RequestCores(allowedParallelism); - ParallelLoopResult result = Parallel.ForEach(Assemblies, - new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, - (assemblyItem, state) => - { - if (!StripAssembly(assemblyItem)) - state.Stop(); - }); - - if (!result.IsCompleted && !Log.HasLoggedErrors) - { - Log.LogError("Unknown failure occurred while IL stripping assemblies. Check logs to get more details."); + int allowedParallelism = DisableParallelStripping ? 1 : Math.Min(Assemblies.Length, Environment.ProcessorCount); + if (BuildEngine is IBuildEngine9 be9) + allowedParallelism = be9.RequestCores(allowedParallelism); + ParallelLoopResult result = Parallel.ForEach(Assemblies, + new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, + (assemblyItem, state) => + { + if (!StripAssembly(assemblyItem)) + state.Stop(); + }); + + if (!result.IsCompleted && !Log.HasLoggedErrors) + { + Log.LogError("Unknown failure occurred while IL stripping assemblies. Check logs to get more details."); + } + + return !Log.HasLoggedErrors; } + else + { + if (MethodTokenFiles.Length == 0) + { + throw new ArgumentException($"'{nameof(MethodTokenFiles)}' is required.", nameof(MethodTokenFiles)); + } - return !Log.HasLoggedErrors; + int allowedParallelism = DisableParallelStripping ? 1 : Math.Min(MethodTokenFiles.Length, Environment.ProcessorCount); + if (BuildEngine is IBuildEngine9 be9) + allowedParallelism = be9.RequestCores(allowedParallelism); + ParallelLoopResult result = Parallel.ForEach(MethodTokenFiles, + new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, + (methodTokenFileItem, state) => + { + if (!TrimMethods(methodTokenFileItem)) + state.Stop(); + }); + + if (!result.IsCompleted && !Log.HasLoggedErrors) + { + Log.LogError("Unknown failure occurred while IL stripping assemblies. Check logs to get more details."); + } + + return !Log.HasLoggedErrors; + } } private bool StripAssembly(ITaskItem assemblyItem) @@ -81,4 +117,91 @@ private bool StripAssembly(ITaskItem assemblyItem) return true; } + private static bool TrimMethods(string methodTokenFileItem, string assemblyPath) + { + if (!File.Exists(methodTokenFileItem)) + { + Log.LogMessage(MessageImportance.Low, $"[ILStrip] {methodTokenFileItem} doesn't exit."); + return true; + } + string[] log = File.ReadAllLines(methodTokenFileItem); + if (log.Length <= 1) + { + // Frist line is assembly name + Log.LogMessage(MessageImportance.Low, $"[ILStrip] {methodTokenFileItem} doesn't contain any compiled method token."); + return true; + } + string assemblyName = log[0]; + int idxCompiledMethods = 1; + string assemblyFilePath = Path.Combine(assemblyPath, (assemblyName + ".dll")); + string trimmedAssemblyFilePath = Path.Combine(assemblyPath, (assemblyName + "_new.dll")); + if (!File.Exists(assemblyFilePath)) + { + Log.LogMessage(MessageImportance.Low, $"[ILStrip] {assemblyFilePath} doesn't exit."); + return true; + } + + using (FileStream fs = File.Open(assemblyFilePath, FileMode.Open), + os = File.Open(trimmedAssemblyFilePath, FileMode.Create)) + { + MemoryStream memStream = new MemoryStream((int)fs.Length); + fs.CopyTo(memStream); + + fs.Position = 0; + PEReader peReader = new PEReader(fs, PEStreamOptions.LeaveOpen); + MetadataReader mr = peReader.GetMetadataReader(); + + foreach (MethodDefinitionHandle mdefh in mr.MethodDefinitions) + { + if (idxCompiledMethods < log.Length) + { + int methodToken = MetadataTokens.GetToken(mr, mdefh); + int expMethodToken = Convert.ToInt32(log[idxCompiledMethods], 16); + + if (methodToken == expMethodToken) + { + MethodDefinition mdef = mr.GetMethodDefinition(mdefh); + int rva = mdef.RelativeVirtualAddress; + + Console.WriteLine(mr.GetString(mdef.Name)); + Console.WriteLine(methodToken); + + MethodBodyBlock mb = peReader.GetMethodBody(rva); + int methodSize = mb.Size; + int sectionIndex = peReader.PEHeaders.GetContainingSectionIndex(rva); + int relativeOffset = rva - peReader.PEHeaders.SectionHeaders[sectionIndex].VirtualAddress; + int actualLoc = peReader.PEHeaders.SectionHeaders[sectionIndex].PointerToRawData + relativeOffset; + + byte[] zeroBuffer = new byte[methodSize]; + for (int i = 0; i < methodSize; i++) + { + zeroBuffer[i] = 0x0; + } + + memStream.Position = actualLoc; + int firstbyte = memStream.ReadByte(); + Console.WriteLine(firstbyte); + + int headerFlag = firstbyte & 0b11; + + int headerSize = headerFlag == 2 ? 1 : 4; + Console.WriteLine(headerSize); + + memStream.Position = actualLoc + headerSize; + memStream.Write(zeroBuffer, 0, methodSize - headerSize); + + idxCompiledMethods++; + } + } + else + { + break; + } + } + memStream.Position = 0; + memStream.CopyTo(os); + } + + return true; + } } From d817f3026e94661e076be7722c3d7089d9b81176 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Wed, 24 May 2023 15:03:51 -0400 Subject: [PATCH 02/27] Fix build errors --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 409e3e1a5648f..86ee14790cb06 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -69,6 +69,11 @@ public override bool Execute() throw new ArgumentException($"'{nameof(MethodTokenFiles)}' is required.", nameof(MethodTokenFiles)); } + if (!Directory.Exists(AssemblyPath)) + { + throw new ArgumentException($"'{nameof(AssemblyPath)}' needs to be a valid path.", nameof(AssemblyPath)); + } + int allowedParallelism = DisableParallelStripping ? 1 : Math.Min(MethodTokenFiles.Length, Environment.ProcessorCount); if (BuildEngine is IBuildEngine9 be9) allowedParallelism = be9.RequestCores(allowedParallelism); @@ -76,7 +81,7 @@ public override bool Execute() new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, (methodTokenFileItem, state) => { - if (!TrimMethods(methodTokenFileItem)) + if (!TrimMethods(methodTokenFileItem, AssemblyPath)) state.Stop(); }); @@ -117,22 +122,23 @@ private bool StripAssembly(ITaskItem assemblyItem) return true; } - private static bool TrimMethods(string methodTokenFileItem, string assemblyPath) + private bool TrimMethods(ITaskItem methodTokenFileItem, string assemblyPath) { - if (!File.Exists(methodTokenFileItem)) + string methodTokenFile = methodTokenFileItem.ItemSpec; + if (!File.Exists(methodTokenFile)) { - Log.LogMessage(MessageImportance.Low, $"[ILStrip] {methodTokenFileItem} doesn't exit."); + Log.LogMessage(MessageImportance.Low, $"[ILStrip] {methodTokenFile} doesn't exit."); return true; } - string[] log = File.ReadAllLines(methodTokenFileItem); + string[] log = File.ReadAllLines(methodTokenFile); if (log.Length <= 1) { // Frist line is assembly name - Log.LogMessage(MessageImportance.Low, $"[ILStrip] {methodTokenFileItem} doesn't contain any compiled method token."); + Log.LogMessage(MessageImportance.Low, $"[ILStrip] {methodTokenFile} doesn't contain any compiled method token."); return true; } string assemblyName = log[0]; - int idxCompiledMethods = 1; + int idxCompiledMethods = 1; string assemblyFilePath = Path.Combine(assemblyPath, (assemblyName + ".dll")); string trimmedAssemblyFilePath = Path.Combine(assemblyPath, (assemblyName + "_new.dll")); if (!File.Exists(assemblyFilePath)) @@ -140,13 +146,13 @@ private static bool TrimMethods(string methodTokenFileItem, string assemblyPath) Log.LogMessage(MessageImportance.Low, $"[ILStrip] {assemblyFilePath} doesn't exit."); return true; } - + using (FileStream fs = File.Open(assemblyFilePath, FileMode.Open), os = File.Open(trimmedAssemblyFilePath, FileMode.Create)) { MemoryStream memStream = new MemoryStream((int)fs.Length); fs.CopyTo(memStream); - + fs.Position = 0; PEReader peReader = new PEReader(fs, PEStreamOptions.LeaveOpen); MetadataReader mr = peReader.GetMetadataReader(); @@ -162,7 +168,7 @@ private static bool TrimMethods(string methodTokenFileItem, string assemblyPath) { MethodDefinition mdef = mr.GetMethodDefinition(mdefh); int rva = mdef.RelativeVirtualAddress; - + Console.WriteLine(mr.GetString(mdef.Name)); Console.WriteLine(methodToken); From 634ef1e2e1e89525d55a40fa121516b3ef51b376 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Wed, 24 May 2023 15:41:12 -0400 Subject: [PATCH 03/27] Remove printf's --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 86ee14790cb06..e83b3fefad2d5 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -169,9 +169,6 @@ private bool TrimMethods(ITaskItem methodTokenFileItem, string assemblyPath) MethodDefinition mdef = mr.GetMethodDefinition(mdefh); int rva = mdef.RelativeVirtualAddress; - Console.WriteLine(mr.GetString(mdef.Name)); - Console.WriteLine(methodToken); - MethodBodyBlock mb = peReader.GetMethodBody(rva); int methodSize = mb.Size; int sectionIndex = peReader.PEHeaders.GetContainingSectionIndex(rva); @@ -186,12 +183,8 @@ private bool TrimMethods(ITaskItem methodTokenFileItem, string assemblyPath) memStream.Position = actualLoc; int firstbyte = memStream.ReadByte(); - Console.WriteLine(firstbyte); - int headerFlag = firstbyte & 0b11; - int headerSize = headerFlag == 2 ? 1 : 4; - Console.WriteLine(headerSize); memStream.Position = actualLoc + headerSize; memStream.Write(zeroBuffer, 0, methodSize - headerSize); From b766c33550f6512e2dc0911a7acf9fa4c51423c8 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Thu, 25 May 2023 10:57:23 -0400 Subject: [PATCH 04/27] Add the option to use compiled-methods-outfile --- src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 30 ++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 553d9dc5a63a3..4a444f22a6fd4 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -152,6 +152,16 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task /// public bool UseDwarfDebug { get; set; } + /// + /// Instructs the AOT compiler to print the list of aot compiled methods + /// + public bool CollectCompiledMethods { get; set; } + + /// + /// Directory to store the aot output when using switch compiled-methods-outfile + /// + public string? CompiledMethodsOutputPath { get; set; } + /// /// File to use for profile-guided optimization, *only* the methods described in the file will be AOT compiled. /// @@ -711,6 +721,26 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st aotArgs.Add("dedup-skip"); } + if (CollectCompiledMethods) + { + if (string.IsNullOrEmpty(CompiledMethodsOutputPath)) + { + Log.LogMessage(MessageImportance.Low, "Skipping collecting the list of aot compiled methods, cause the value of CompiledMethodsOutputPath is empty."); + } + else + { + if (!Directory.Exists(CompiledMethodsOutputPath)) + { + Directory.CreateDirectory(CompiledMethodsOutputPath); + } + string assemblyFileName = Path.GetFileName(assembly); + string assemblyName = assemblyFileName.Replace(".", "_"); + string outputFileName = assemblyName + "_compiled_methods.txt"; + string outputFilePath = Path.Combine(CompiledMethodsOutputPath, outputFileName); + aotArgs.Add($"compiled-methods-outfile={outputFilePath}"); + } + } + // compute output mode and file names if (parsedAotMode == MonoAotMode.LLVMOnly || parsedAotMode == MonoAotMode.LLVMOnlyInterp) { From 10b3b0160b0e6163fbb7a974dc682743bfae1c9e Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Fri, 26 May 2023 17:04:38 -0400 Subject: [PATCH 05/27] Avoid trimming shared methods when they are still in use --- src/mono/mono/mini/aot-compiler.c | 5 +- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 80 +++++++++++-------- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 040c37d665bc2..d09144d0c13a8 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -9828,8 +9828,9 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) mono_atomic_inc_i32 (&acfg->stats.ccount); if (acfg->aot_opts.compiled_methods_outfile && acfg->compiled_methods_outfile != NULL) { - if (!mono_method_is_generic_impl (method) && method->token != 0) - fprintf (acfg->compiled_methods_outfile, "%x\n", method->token); + if (!mono_method_is_generic_impl (method) && method->token != 0) { + fprintf (acfg->compiled_methods_outfile, "%d\n", method->token); + } } } diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index e83b3fefad2d5..076d83e496742 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -138,7 +138,6 @@ private bool TrimMethods(ITaskItem methodTokenFileItem, string assemblyPath) return true; } string assemblyName = log[0]; - int idxCompiledMethods = 1; string assemblyFilePath = Path.Combine(assemblyPath, (assemblyName + ".dll")); string trimmedAssemblyFilePath = Path.Combine(assemblyPath, (assemblyName + "_new.dll")); if (!File.Exists(assemblyFilePath)) @@ -157,44 +156,59 @@ private bool TrimMethods(ITaskItem methodTokenFileItem, string assemblyPath) PEReader peReader = new PEReader(fs, PEStreamOptions.LeaveOpen); MetadataReader mr = peReader.GetMetadataReader(); + Dictionary token_to_rva = new Dictionary(); + Dictionary method_body_uses = new Dictionary(); + foreach (MethodDefinitionHandle mdefh in mr.MethodDefinitions) { - if (idxCompiledMethods < log.Length) - { - int methodToken = MetadataTokens.GetToken(mr, mdefh); - int expMethodToken = Convert.ToInt32(log[idxCompiledMethods], 16); + int methodToken = MetadataTokens.GetToken(mr, mdefh); + MethodDefinition mdef = mr.GetMethodDefinition(mdefh); + int rva = mdef.RelativeVirtualAddress; - if (methodToken == expMethodToken) - { - MethodDefinition mdef = mr.GetMethodDefinition(mdefh); - int rva = mdef.RelativeVirtualAddress; - - MethodBodyBlock mb = peReader.GetMethodBody(rva); - int methodSize = mb.Size; - int sectionIndex = peReader.PEHeaders.GetContainingSectionIndex(rva); - int relativeOffset = rva - peReader.PEHeaders.SectionHeaders[sectionIndex].VirtualAddress; - int actualLoc = peReader.PEHeaders.SectionHeaders[sectionIndex].PointerToRawData + relativeOffset; - - byte[] zeroBuffer = new byte[methodSize]; - for (int i = 0; i < methodSize; i++) - { - zeroBuffer[i] = 0x0; - } - - memStream.Position = actualLoc; - int firstbyte = memStream.ReadByte(); - int headerFlag = firstbyte & 0b11; - int headerSize = headerFlag == 2 ? 1 : 4; - - memStream.Position = actualLoc + headerSize; - memStream.Write(zeroBuffer, 0, methodSize - headerSize); - - idxCompiledMethods++; - } + token_to_rva.Add(methodToken, rva); + + if (method_body_uses.TryGetValue(rva, out var count)) + { + method_body_uses[rva]++; } else { - break; + method_body_uses.Add(rva, 1); + } + } + + for (int i = 1; i < log.Length; i++) + { + int methodToken2Trim = Convert.ToInt32(log[i]); + int rva2Trim = token_to_rva[methodToken2Trim]; + method_body_uses[rva2Trim]--; + } + + foreach (var kvp in method_body_uses) + { + int rva = kvp.Key; + int count = kvp.Value; + if (count == 0) + { + MethodBodyBlock mb = peReader.GetMethodBody(rva); + int methodSize = mb.Size; + int sectionIndex = peReader.PEHeaders.GetContainingSectionIndex(rva); + int relativeOffset = rva - peReader.PEHeaders.SectionHeaders[sectionIndex].VirtualAddress; + int actualLoc = peReader.PEHeaders.SectionHeaders[sectionIndex].PointerToRawData + relativeOffset; + + byte[] zeroBuffer = new byte[methodSize]; + for (int i = 0; i < methodSize; i++) + { + zeroBuffer[i] = 0x0; + } + + memStream.Position = actualLoc; + int firstbyte = memStream.ReadByte(); + int headerFlag = firstbyte & 0b11; + int headerSize = headerFlag == 2 ? 1 : 4; + + memStream.Position = actualLoc + headerSize; + memStream.Write(zeroBuffer, 0, methodSize - headerSize); } } memStream.Position = 0; From 2bc884e3cda9f2a1910591bd475d687255dee741 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Fri, 26 May 2023 17:25:13 -0400 Subject: [PATCH 06/27] Add parameter description --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 076d83e496742..8595899fc2930 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -29,10 +29,19 @@ public class ILStrip : Microsoft.Build.Utilities.Task /// public bool DisableParallelStripping { get; set; } + /// + /// Enable the feature of trimming indiviual methods + /// public bool TrimIndividualMethods { get; set; } + /// + /// Methods to be trimmed, identified by method token + /// public ITaskItem[] MethodTokenFiles { get; set; } = Array.Empty(); + /// + /// Directory where all the assemblies are stored + /// public string AssemblyPath { get; set; } = ""; public override bool Execute() From b23d8332d65eaad26c64d1eaa804d5afc2784e0c Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Fri, 26 May 2023 17:37:40 -0400 Subject: [PATCH 07/27] Add the option to trim compiled methods --- src/mono/sample/HelloWorld/HelloWorld.csproj | 21 ++++++++++++++++++++ src/mono/sample/HelloWorld/Makefile | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/src/mono/sample/HelloWorld/HelloWorld.csproj b/src/mono/sample/HelloWorld/HelloWorld.csproj index b4e843e802673..212a2945563b2 100644 --- a/src/mono/sample/HelloWorld/HelloWorld.csproj +++ b/src/mono/sample/HelloWorld/HelloWorld.csproj @@ -25,6 +25,8 @@ LibraryFormat="$(_AotLibraryFormat)" Assemblies="@(AotInputAssemblies)" OutputDir="$(PublishDir)" + CollectCompiledMethods="$(StripILCode)" + CompiledMethodsOutputPath="$(MethodTokenFilePath)" IntermediateOutputPath="$(IntermediateOutputPath)" UseAotDataFile="$(UseAotDataFile)" CacheFilePath="$(IntermediateOutputPath)aot_compiler_cache.json" @@ -35,4 +37,23 @@ + + + + + + true + + + + + + + + + diff --git a/src/mono/sample/HelloWorld/Makefile b/src/mono/sample/HelloWorld/Makefile index 8b18dc45c65a0..f7f31dffdbc6b 100644 --- a/src/mono/sample/HelloWorld/Makefile +++ b/src/mono/sample/HelloWorld/Makefile @@ -6,6 +6,8 @@ MONO_CONFIG?=Debug MONO_ARCH?=$(shell . $(TOP)eng/native/init-os-and-arch.sh && echo $${arch}) TARGET_OS?=$(shell . $(TOP)eng/native/init-os-and-arch.sh && echo $${os}) AOT?=false +StripILCode?=false +MethodTokenFilePath?= # #NET_TRACE_PATH= #PGO_BINARY_PATH= @@ -18,6 +20,8 @@ publish: -c $(MONO_CONFIG) \ -r $(TARGET_OS)-$(MONO_ARCH) \ /p:RunAOTCompilation=$(AOT) \ + /p:StripILCode=$(StripILCode) \ + /p:MethodTokenFilePath=$(MethodTokenFilePath) \ '/p:NetTracePath="$(NET_TRACE_PATH)"' \ '/p:PgoBinaryPath="$(PGO_BINARY_PATH)"' \ '/p:MibcProfilePath="$(MIBC_PROFILE_PATH)"' From f6d99d7a2a541eb6aa24c7fcb6ce6a0af2ddb7f8 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Wed, 31 May 2023 10:42:52 -0400 Subject: [PATCH 08/27] Address review feedback --- src/mono/mono/mini/aot-compiler.c | 2 +- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 170 ++++++++++-------- 2 files changed, 94 insertions(+), 78 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index d09144d0c13a8..bf8e8a6998d19 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -14831,7 +14831,7 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) if (acfg->aot_opts.compiled_methods_outfile && acfg->dedup_phase != DEDUP_COLLECT) { acfg->compiled_methods_outfile = fopen (acfg->aot_opts.compiled_methods_outfile, "w+"); - fprintf(acfg->compiled_methods_outfile, "%s\n", ass->aname.name); + fprintf(acfg->compiled_methods_outfile, "%s\n", ass->image->filename); if (!acfg->compiled_methods_outfile) aot_printerrf (acfg, "Unable to open compiled-methods-outfile specified file %s\n", acfg->aot_opts.compiled_methods_outfile); diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 8595899fc2930..59073079f852d 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -15,6 +15,7 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; +using System.Buffers; public class ILStrip : Microsoft.Build.Utilities.Task { @@ -39,11 +40,6 @@ public class ILStrip : Microsoft.Build.Utilities.Task /// public ITaskItem[] MethodTokenFiles { get; set; } = Array.Empty(); - /// - /// Directory where all the assemblies are stored - /// - public string AssemblyPath { get; set; } = ""; - public override bool Execute() { if (!TrimIndividualMethods) @@ -78,11 +74,6 @@ public override bool Execute() throw new ArgumentException($"'{nameof(MethodTokenFiles)}' is required.", nameof(MethodTokenFiles)); } - if (!Directory.Exists(AssemblyPath)) - { - throw new ArgumentException($"'{nameof(AssemblyPath)}' needs to be a valid path.", nameof(AssemblyPath)); - } - int allowedParallelism = DisableParallelStripping ? 1 : Math.Min(MethodTokenFiles.Length, Environment.ProcessorCount); if (BuildEngine is IBuildEngine9 be9) allowedParallelism = be9.RequestCores(allowedParallelism); @@ -90,7 +81,7 @@ public override bool Execute() new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, (methodTokenFileItem, state) => { - if (!TrimMethods(methodTokenFileItem, AssemblyPath)) + if (!TrimMethods(methodTokenFileItem)) state.Stop(); }); @@ -131,7 +122,7 @@ private bool StripAssembly(ITaskItem assemblyItem) return true; } - private bool TrimMethods(ITaskItem methodTokenFileItem, string assemblyPath) + private bool TrimMethods(ITaskItem methodTokenFileItem) { string methodTokenFile = methodTokenFileItem.ItemSpec; if (!File.Exists(methodTokenFile)) @@ -139,89 +130,114 @@ private bool TrimMethods(ITaskItem methodTokenFileItem, string assemblyPath) Log.LogMessage(MessageImportance.Low, $"[ILStrip] {methodTokenFile} doesn't exit."); return true; } - string[] log = File.ReadAllLines(methodTokenFile); - if (log.Length <= 1) - { - // Frist line is assembly name - Log.LogMessage(MessageImportance.Low, $"[ILStrip] {methodTokenFile} doesn't contain any compiled method token."); - return true; - } - string assemblyName = log[0]; - string assemblyFilePath = Path.Combine(assemblyPath, (assemblyName + ".dll")); - string trimmedAssemblyFilePath = Path.Combine(assemblyPath, (assemblyName + "_new.dll")); - if (!File.Exists(assemblyFilePath)) - { - Log.LogMessage(MessageImportance.Low, $"[ILStrip] {assemblyFilePath} doesn't exit."); - return true; - } - using (FileStream fs = File.Open(assemblyFilePath, FileMode.Open), - os = File.Open(trimmedAssemblyFilePath, FileMode.Create)) + using (StreamReader sr = new StreamReader(methodTokenFile)) { - MemoryStream memStream = new MemoryStream((int)fs.Length); - fs.CopyTo(memStream); - - fs.Position = 0; - PEReader peReader = new PEReader(fs, PEStreamOptions.LeaveOpen); - MetadataReader mr = peReader.GetMetadataReader(); - - Dictionary token_to_rva = new Dictionary(); - Dictionary method_body_uses = new Dictionary(); - - foreach (MethodDefinitionHandle mdefh in mr.MethodDefinitions) + string? assemblyFilePath = sr.ReadLine(); + if (string.IsNullOrEmpty(assemblyFilePath)) { - int methodToken = MetadataTokens.GetToken(mr, mdefh); - MethodDefinition mdef = mr.GetMethodDefinition(mdefh); - int rva = mdef.RelativeVirtualAddress; + return true; + } - token_to_rva.Add(methodToken, rva); + if (!File.Exists(assemblyFilePath)) + { + Log.LogMessage(MessageImportance.Low, $"[ILStrip] {assemblyFilePath} doesn't exit."); + return true; + } - if (method_body_uses.TryGetValue(rva, out var count)) + string? line = sr.ReadLine(); + if (!string.IsNullOrEmpty(line)) + { + string? assemblyPath = Path.GetDirectoryName(assemblyFilePath); + string? assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath); + string trimmedAssemblyFilePath; + string newName_assemblyFilePath; + if (string.IsNullOrEmpty(assemblyPath)) { - method_body_uses[rva]++; + trimmedAssemblyFilePath = assemblyName + "_new.dll"; + newName_assemblyFilePath = assemblyName + "_old.dll"; } else { - method_body_uses.Add(rva, 1); + trimmedAssemblyFilePath = Path.Combine(assemblyPath, (assemblyName + "_new.dll")); + newName_assemblyFilePath = Path.Combine(assemblyPath, (assemblyName + "_old.dll")); } - } - for (int i = 1; i < log.Length; i++) - { - int methodToken2Trim = Convert.ToInt32(log[i]); - int rva2Trim = token_to_rva[methodToken2Trim]; - method_body_uses[rva2Trim]--; - } - - foreach (var kvp in method_body_uses) - { - int rva = kvp.Key; - int count = kvp.Value; - if (count == 0) + using (FileStream fs = File.Open(assemblyFilePath, FileMode.Open), + os = File.Open(trimmedAssemblyFilePath, FileMode.Create)) { - MethodBodyBlock mb = peReader.GetMethodBody(rva); - int methodSize = mb.Size; - int sectionIndex = peReader.PEHeaders.GetContainingSectionIndex(rva); - int relativeOffset = rva - peReader.PEHeaders.SectionHeaders[sectionIndex].VirtualAddress; - int actualLoc = peReader.PEHeaders.SectionHeaders[sectionIndex].PointerToRawData + relativeOffset; - - byte[] zeroBuffer = new byte[methodSize]; - for (int i = 0; i < methodSize; i++) + MemoryStream memStream = new MemoryStream((int)fs.Length); + fs.CopyTo(memStream); + + fs.Position = 0; + PEReader peReader = new PEReader(fs, PEStreamOptions.LeaveOpen); + MetadataReader mr = peReader.GetMetadataReader(); + + Dictionary token_to_rva = new Dictionary(); + Dictionary method_body_uses = new Dictionary(); + + foreach (MethodDefinitionHandle mdefh in mr.MethodDefinitions) { - zeroBuffer[i] = 0x0; + int methodToken = MetadataTokens.GetToken(mr, mdefh); + MethodDefinition mdef = mr.GetMethodDefinition(mdefh); + int rva = mdef.RelativeVirtualAddress; + + token_to_rva.Add(methodToken, rva); + + if (method_body_uses.TryGetValue(rva, out var count)) + { + method_body_uses[rva]++; + } + else + { + method_body_uses.Add(rva, 1); + } } - memStream.Position = actualLoc; - int firstbyte = memStream.ReadByte(); - int headerFlag = firstbyte & 0b11; - int headerSize = headerFlag == 2 ? 1 : 4; + do + { + int methodToken2Trim = Convert.ToInt32(line); + int rva2Trim = token_to_rva[methodToken2Trim]; + method_body_uses[rva2Trim]--; + } while ((line = sr.ReadLine()) != null); - memStream.Position = actualLoc + headerSize; - memStream.Write(zeroBuffer, 0, methodSize - headerSize); + foreach (var kvp in method_body_uses) + { + int rva = kvp.Key; + int count = kvp.Value; + if (count == 0) + { + MethodBodyBlock mb = peReader.GetMethodBody(rva); + int methodSize = mb.Size; + int sectionIndex = peReader.PEHeaders.GetContainingSectionIndex(rva); + int relativeOffset = rva - peReader.PEHeaders.SectionHeaders[sectionIndex].VirtualAddress; + int actualLoc = peReader.PEHeaders.SectionHeaders[sectionIndex].PointerToRawData + relativeOffset; + + byte[] zeroBuffer; + zeroBuffer = ArrayPool.Shared.Rent(methodSize); + for (int i = 0; i < zeroBuffer.Length; i++) + { + zeroBuffer[i] = 0x0; + } + + memStream.Position = actualLoc; + int firstbyte = memStream.ReadByte(); + int headerFlag = firstbyte & 0b11; + int headerSize = headerFlag == 2 ? 1 : 4; + + memStream.Position = actualLoc + headerSize; + memStream.Write(zeroBuffer, 0, methodSize - headerSize); + + ArrayPool.Shared.Return(zeroBuffer); + } + } + memStream.Position = 0; + memStream.CopyTo(os); } + + File.Move(assemblyFilePath, newName_assemblyFilePath); + File.Move(trimmedAssemblyFilePath, assemblyFilePath); } - memStream.Position = 0; - memStream.CopyTo(os); } return true; From 69bf960b7d7ac77b70fdbce7ee30df0cec100bf9 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Wed, 31 May 2023 15:23:57 -0400 Subject: [PATCH 09/27] Add metadata MethodTokenFile to CompiledAssemblies --- src/mono/sample/HelloWorld/HelloWorld.csproj | 7 +------ src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 2 ++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/mono/sample/HelloWorld/HelloWorld.csproj b/src/mono/sample/HelloWorld/HelloWorld.csproj index 212a2945563b2..1eaf88ee87684 100644 --- a/src/mono/sample/HelloWorld/HelloWorld.csproj +++ b/src/mono/sample/HelloWorld/HelloWorld.csproj @@ -46,14 +46,9 @@ true - - - - + MethodTokenFiles="@(BundleAssemblies->'%(MethodTokenFile)')"> diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 4a444f22a6fd4..90960edba0162 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -67,6 +67,7 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task /// - LlvmObjectFile (if using LLVM) /// - LlvmBitcodeFile (if using LLVM-only) /// - ExportsFile (used in LibraryMode only) + /// - MethodTokenFile (when using CollectCompiledMethods=true) /// [Output] public ITaskItem[]? CompiledAssemblies { get; set; } @@ -738,6 +739,7 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st string outputFileName = assemblyName + "_compiled_methods.txt"; string outputFilePath = Path.Combine(CompiledMethodsOutputPath, outputFileName); aotArgs.Add($"compiled-methods-outfile={outputFilePath}"); + aotAssembly.SetMetadata("MethodTokenFile", outputFilePath); } } From 1f0fcbbf6817cd4860988c68a4688927841fbcee Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Fri, 2 Jun 2023 10:28:53 -0400 Subject: [PATCH 10/27] Add GUID checks and use metadata of assemblies --- src/mono/mono/mini/aot-compiler.c | 6 +- src/mono/sample/HelloWorld/HelloWorld.csproj | 2 +- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 231 +++++++++--------- 3 files changed, 116 insertions(+), 123 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index bf8e8a6998d19..441d5852dda52 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -14831,10 +14831,12 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) if (acfg->aot_opts.compiled_methods_outfile && acfg->dedup_phase != DEDUP_COLLECT) { acfg->compiled_methods_outfile = fopen (acfg->aot_opts.compiled_methods_outfile, "w+"); - fprintf(acfg->compiled_methods_outfile, "%s\n", ass->image->filename); - if (!acfg->compiled_methods_outfile) aot_printerrf (acfg, "Unable to open compiled-methods-outfile specified file %s\n", acfg->aot_opts.compiled_methods_outfile); + else { + fprintf(acfg->compiled_methods_outfile, "%s\n", ass->image->filename); + fprintf(acfg->compiled_methods_outfile, "%s\n", ass->image->guid); + } } if (acfg->aot_opts.data_outfile) { diff --git a/src/mono/sample/HelloWorld/HelloWorld.csproj b/src/mono/sample/HelloWorld/HelloWorld.csproj index 1eaf88ee87684..975b1fd4572ee 100644 --- a/src/mono/sample/HelloWorld/HelloWorld.csproj +++ b/src/mono/sample/HelloWorld/HelloWorld.csproj @@ -48,7 +48,7 @@ + Assemblies="@(BundleAssemblies)"> diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 59073079f852d..5dcb039524e5c 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -19,6 +19,7 @@ public class ILStrip : Microsoft.Build.Utilities.Task { + [Required] /// /// Assemblies to be stripped. /// The assemblies will be modified in place if OutputPath metadata is not set. @@ -35,63 +36,38 @@ public class ILStrip : Microsoft.Build.Utilities.Task /// public bool TrimIndividualMethods { get; set; } - /// - /// Methods to be trimmed, identified by method token - /// - public ITaskItem[] MethodTokenFiles { get; set; } = Array.Empty(); - public override bool Execute() { - if (!TrimIndividualMethods) + if (Assemblies.Length == 0) { - if (Assemblies.Length == 0) - { - throw new ArgumentException($"'{nameof(Assemblies)}' is required.", nameof(Assemblies)); - } + throw new ArgumentException($"'{nameof(Assemblies)}' is required.", nameof(Assemblies)); + } - int allowedParallelism = DisableParallelStripping ? 1 : Math.Min(Assemblies.Length, Environment.ProcessorCount); - if (BuildEngine is IBuildEngine9 be9) - allowedParallelism = be9.RequestCores(allowedParallelism); - ParallelLoopResult result = Parallel.ForEach(Assemblies, - new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, - (assemblyItem, state) => + int allowedParallelism = DisableParallelStripping ? 1 : Math.Min(Assemblies.Length, Environment.ProcessorCount); + if (BuildEngine is IBuildEngine9 be9) + allowedParallelism = be9.RequestCores(allowedParallelism); + ParallelLoopResult result = Parallel.ForEach(Assemblies, + new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, + (assemblyItem, state) => + { + if (!TrimIndividualMethods) { if (!StripAssembly(assemblyItem)) state.Stop(); - }); - - if (!result.IsCompleted && !Log.HasLoggedErrors) - { - Log.LogError("Unknown failure occurred while IL stripping assemblies. Check logs to get more details."); - } - - return !Log.HasLoggedErrors; - } - else - { - if (MethodTokenFiles.Length == 0) - { - throw new ArgumentException($"'{nameof(MethodTokenFiles)}' is required.", nameof(MethodTokenFiles)); - } - - int allowedParallelism = DisableParallelStripping ? 1 : Math.Min(MethodTokenFiles.Length, Environment.ProcessorCount); - if (BuildEngine is IBuildEngine9 be9) - allowedParallelism = be9.RequestCores(allowedParallelism); - ParallelLoopResult result = Parallel.ForEach(MethodTokenFiles, - new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, - (methodTokenFileItem, state) => + } + else { - if (!TrimMethods(methodTokenFileItem)) + if (!TrimMethods(assemblyItem)) state.Stop(); - }); - - if (!result.IsCompleted && !Log.HasLoggedErrors) - { - Log.LogError("Unknown failure occurred while IL stripping assemblies. Check logs to get more details."); - } + } + }); - return !Log.HasLoggedErrors; + if (!result.IsCompleted && !Log.HasLoggedErrors) + { + Log.LogError("Unknown failure occurred while IL stripping assemblies. Check logs to get more details."); } + + return !Log.HasLoggedErrors; } private bool StripAssembly(ITaskItem assemblyItem) @@ -122,9 +98,9 @@ private bool StripAssembly(ITaskItem assemblyItem) return true; } - private bool TrimMethods(ITaskItem methodTokenFileItem) + private bool TrimMethods(ITaskItem assemblyItem) { - string methodTokenFile = methodTokenFileItem.ItemSpec; + string methodTokenFile = assemblyItem.GetMetadata("MethodTokenFile"); if (!File.Exists(methodTokenFile)) { Log.LogMessage(MessageImportance.Low, $"[ILStrip] {methodTokenFile} doesn't exit."); @@ -145,97 +121,112 @@ private bool TrimMethods(ITaskItem methodTokenFileItem) return true; } - string? line = sr.ReadLine(); - if (!string.IsNullOrEmpty(line)) + string? assemblyPath = Path.GetDirectoryName(assemblyFilePath); + string? assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath); + string trimmedAssemblyFilePath; + if (string.IsNullOrEmpty(assemblyPath)) { - string? assemblyPath = Path.GetDirectoryName(assemblyFilePath); - string? assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath); - string trimmedAssemblyFilePath; - string newName_assemblyFilePath; - if (string.IsNullOrEmpty(assemblyPath)) - { - trimmedAssemblyFilePath = assemblyName + "_new.dll"; - newName_assemblyFilePath = assemblyName + "_old.dll"; - } - else + trimmedAssemblyFilePath = assemblyName + "_new.dll"; + } + else + { + trimmedAssemblyFilePath = Path.Combine(assemblyPath, (assemblyName + "_new.dll")); + } + + bool isTrimmed = false; + using (FileStream fs = File.Open(assemblyFilePath, FileMode.Open)) + { + PEReader peReader = new PEReader(fs, PEStreamOptions.LeaveOpen); + MetadataReader mr = peReader.GetMetadataReader(); + + GuidHandle mvidHandle = mr.GetModuleDefinition().Mvid; + Guid mvid = mr.GetGuid(mvidHandle); + string guidValue = mvid.ToString(); + + string? expectedGuidValue = sr.ReadLine(); + if (!string.Equals(guidValue, expectedGuidValue, StringComparison.OrdinalIgnoreCase)) { - trimmedAssemblyFilePath = Path.Combine(assemblyPath, (assemblyName + "_new.dll")); - newName_assemblyFilePath = Path.Combine(assemblyPath, (assemblyName + "_old.dll")); + Log.LogMessage(MessageImportance.Low, $"[ILStrip] GUID value of {assemblyFilePath} doesn't match the value listed in {methodTokenFile}."); + return true; } - using (FileStream fs = File.Open(assemblyFilePath, FileMode.Open), - os = File.Open(trimmedAssemblyFilePath, FileMode.Create)) + string? line = sr.ReadLine(); + if (!string.IsNullOrEmpty(line)) { - MemoryStream memStream = new MemoryStream((int)fs.Length); - fs.CopyTo(memStream); + using (FileStream os = File.Open(trimmedAssemblyFilePath, FileMode.Create)) + { + isTrimmed = true; + fs.Position = 0; + MemoryStream memStream = new MemoryStream((int)fs.Length); + fs.CopyTo(memStream); - fs.Position = 0; - PEReader peReader = new PEReader(fs, PEStreamOptions.LeaveOpen); - MetadataReader mr = peReader.GetMetadataReader(); + Dictionary token_to_rva = new Dictionary(); + Dictionary method_body_uses = new Dictionary(); - Dictionary token_to_rva = new Dictionary(); - Dictionary method_body_uses = new Dictionary(); + foreach (MethodDefinitionHandle mdefh in mr.MethodDefinitions) + { + int methodToken = MetadataTokens.GetToken(mr, mdefh); + MethodDefinition mdef = mr.GetMethodDefinition(mdefh); - foreach (MethodDefinitionHandle mdefh in mr.MethodDefinitions) - { - int methodToken = MetadataTokens.GetToken(mr, mdefh); - MethodDefinition mdef = mr.GetMethodDefinition(mdefh); - int rva = mdef.RelativeVirtualAddress; + int rva = mdef.RelativeVirtualAddress; - token_to_rva.Add(methodToken, rva); + token_to_rva.Add(methodToken, rva); - if (method_body_uses.TryGetValue(rva, out var count)) - { - method_body_uses[rva]++; - } - else - { - method_body_uses.Add(rva, 1); + if (method_body_uses.TryGetValue(rva, out var count)) + { + method_body_uses[rva]++; + } + else + { + method_body_uses.Add(rva, 1); + } } - } - do - { - int methodToken2Trim = Convert.ToInt32(line); - int rva2Trim = token_to_rva[methodToken2Trim]; - method_body_uses[rva2Trim]--; - } while ((line = sr.ReadLine()) != null); + do + { + int methodToken2Trim = Convert.ToInt32(line); + int rva2Trim = token_to_rva[methodToken2Trim]; + method_body_uses[rva2Trim]--; + } while ((line = sr.ReadLine()) != null); - foreach (var kvp in method_body_uses) - { - int rva = kvp.Key; - int count = kvp.Value; - if (count == 0) + foreach (var kvp in method_body_uses) { - MethodBodyBlock mb = peReader.GetMethodBody(rva); - int methodSize = mb.Size; - int sectionIndex = peReader.PEHeaders.GetContainingSectionIndex(rva); - int relativeOffset = rva - peReader.PEHeaders.SectionHeaders[sectionIndex].VirtualAddress; - int actualLoc = peReader.PEHeaders.SectionHeaders[sectionIndex].PointerToRawData + relativeOffset; - - byte[] zeroBuffer; - zeroBuffer = ArrayPool.Shared.Rent(methodSize); - for (int i = 0; i < zeroBuffer.Length; i++) + int rva = kvp.Key; + int count = kvp.Value; + if (count == 0) { - zeroBuffer[i] = 0x0; + MethodBodyBlock mb = peReader.GetMethodBody(rva); + int methodSize = mb.Size; + int sectionIndex = peReader.PEHeaders.GetContainingSectionIndex(rva); + int relativeOffset = rva - peReader.PEHeaders.SectionHeaders[sectionIndex].VirtualAddress; + int actualLoc = peReader.PEHeaders.SectionHeaders[sectionIndex].PointerToRawData + relativeOffset; + + byte[] zeroBuffer; + zeroBuffer = ArrayPool.Shared.Rent(methodSize); + for (int i = 0; i < zeroBuffer.Length; i++) + { + zeroBuffer[i] = 0x0; + } + + memStream.Position = actualLoc; + int firstbyte = memStream.ReadByte(); + int headerFlag = firstbyte & 0b11; + int headerSize = headerFlag == 2 ? 1 : 4; + + memStream.Position = actualLoc + headerSize; + memStream.Write(zeroBuffer, 0, methodSize - headerSize); + + ArrayPool.Shared.Return(zeroBuffer); } - - memStream.Position = actualLoc; - int firstbyte = memStream.ReadByte(); - int headerFlag = firstbyte & 0b11; - int headerSize = headerFlag == 2 ? 1 : 4; - - memStream.Position = actualLoc + headerSize; - memStream.Write(zeroBuffer, 0, methodSize - headerSize); - - ArrayPool.Shared.Return(zeroBuffer); } + memStream.Position = 0; + memStream.CopyTo(os); } - memStream.Position = 0; - memStream.CopyTo(os); } - - File.Move(assemblyFilePath, newName_assemblyFilePath); + } + if (isTrimmed) + { + File.Delete(assemblyFilePath); File.Move(trimmedAssemblyFilePath, assemblyFilePath); } } From eaa939cc930d06c46f4006e30a9e09c55a93cd2e Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Fri, 2 Jun 2023 16:17:25 -0400 Subject: [PATCH 11/27] Create smaller functions and use hex value --- src/mono/mono/mini/aot-compiler.c | 2 +- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 212 +++++++++++------- 2 files changed, 126 insertions(+), 88 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 441d5852dda52..60d68481cc417 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -9829,7 +9829,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) if (acfg->aot_opts.compiled_methods_outfile && acfg->compiled_methods_outfile != NULL) { if (!mono_method_is_generic_impl (method) && method->token != 0) { - fprintf (acfg->compiled_methods_outfile, "%d\n", method->token); + fprintf (acfg->compiled_methods_outfile, "%x\n", method->token); } } } diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 5dcb039524e5c..42a0983882fa7 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -121,28 +121,15 @@ private bool TrimMethods(ITaskItem assemblyItem) return true; } - string? assemblyPath = Path.GetDirectoryName(assemblyFilePath); - string? assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath); - string trimmedAssemblyFilePath; - if (string.IsNullOrEmpty(assemblyPath)) - { - trimmedAssemblyFilePath = assemblyName + "_new.dll"; - } - else - { - trimmedAssemblyFilePath = Path.Combine(assemblyPath, (assemblyName + "_new.dll")); - } - + string trimmedAssemblyFilePath = ComputeTrimmedAssemblyPath(assemblyFilePath); bool isTrimmed = false; + using (FileStream fs = File.Open(assemblyFilePath, FileMode.Open)) { PEReader peReader = new PEReader(fs, PEStreamOptions.LeaveOpen); MetadataReader mr = peReader.GetMetadataReader(); - GuidHandle mvidHandle = mr.GetModuleDefinition().Mvid; - Guid mvid = mr.GetGuid(mvidHandle); - string guidValue = mvid.ToString(); - + string guidValue = ComputeGuid(mr); string? expectedGuidValue = sr.ReadLine(); if (!string.Equals(guidValue, expectedGuidValue, StringComparison.OrdinalIgnoreCase)) { @@ -153,84 +140,135 @@ private bool TrimMethods(ITaskItem assemblyItem) string? line = sr.ReadLine(); if (!string.IsNullOrEmpty(line)) { - using (FileStream os = File.Open(trimmedAssemblyFilePath, FileMode.Create)) - { - isTrimmed = true; - fs.Position = 0; - MemoryStream memStream = new MemoryStream((int)fs.Length); - fs.CopyTo(memStream); - - Dictionary token_to_rva = new Dictionary(); - Dictionary method_body_uses = new Dictionary(); - - foreach (MethodDefinitionHandle mdefh in mr.MethodDefinitions) - { - int methodToken = MetadataTokens.GetToken(mr, mdefh); - MethodDefinition mdef = mr.GetMethodDefinition(mdefh); - - int rva = mdef.RelativeVirtualAddress; - - token_to_rva.Add(methodToken, rva); - - if (method_body_uses.TryGetValue(rva, out var count)) - { - method_body_uses[rva]++; - } - else - { - method_body_uses.Add(rva, 1); - } - } - - do - { - int methodToken2Trim = Convert.ToInt32(line); - int rva2Trim = token_to_rva[methodToken2Trim]; - method_body_uses[rva2Trim]--; - } while ((line = sr.ReadLine()) != null); - - foreach (var kvp in method_body_uses) - { - int rva = kvp.Key; - int count = kvp.Value; - if (count == 0) - { - MethodBodyBlock mb = peReader.GetMethodBody(rva); - int methodSize = mb.Size; - int sectionIndex = peReader.PEHeaders.GetContainingSectionIndex(rva); - int relativeOffset = rva - peReader.PEHeaders.SectionHeaders[sectionIndex].VirtualAddress; - int actualLoc = peReader.PEHeaders.SectionHeaders[sectionIndex].PointerToRawData + relativeOffset; - - byte[] zeroBuffer; - zeroBuffer = ArrayPool.Shared.Rent(methodSize); - for (int i = 0; i < zeroBuffer.Length; i++) - { - zeroBuffer[i] = 0x0; - } - - memStream.Position = actualLoc; - int firstbyte = memStream.ReadByte(); - int headerFlag = firstbyte & 0b11; - int headerSize = headerFlag == 2 ? 1 : 4; - - memStream.Position = actualLoc + headerSize; - memStream.Write(zeroBuffer, 0, methodSize - headerSize); - - ArrayPool.Shared.Return(zeroBuffer); - } - } - memStream.Position = 0; - memStream.CopyTo(os); - } + isTrimmed = true; + Dictionary method_body_uses = ComputeMethodBodyUsage(mr, sr, line); + CreateTrimmedAssembly(peReader, trimmedAssemblyFilePath, fs, method_body_uses); } } if (isTrimmed) { - File.Delete(assemblyFilePath); - File.Move(trimmedAssemblyFilePath, assemblyFilePath); + ReplaceAssemblyWithTrimmedOne(assemblyFilePath, trimmedAssemblyFilePath); } } return true; } + + private static string ComputeTrimmedAssemblyPath(string assemblyFilePath) + { + string? assemblyPath = Path.GetDirectoryName(assemblyFilePath); + string? assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath); + if (string.IsNullOrEmpty(assemblyPath)) + { + return (assemblyName + "_new.dll"); + } + else + { + return Path.Combine(assemblyPath, (assemblyName + "_new.dll")); + } + } + + private static string ComputeGuid(MetadataReader mr) + { + GuidHandle mvidHandle = mr.GetModuleDefinition().Mvid; + Guid mvid = mr.GetGuid(mvidHandle); + return mvid.ToString(); + } + + private static Dictionary ComputeMethodBodyUsage(MetadataReader mr, StreamReader sr, string? line) + { + Dictionary token_to_rva = new Dictionary(); + Dictionary method_body_uses = new Dictionary(); + + foreach (MethodDefinitionHandle mdefh in mr.MethodDefinitions) + { + int methodToken = MetadataTokens.GetToken(mr, mdefh); + MethodDefinition mdef = mr.GetMethodDefinition(mdefh); + int rva = mdef.RelativeVirtualAddress; + + token_to_rva.Add(methodToken, rva); + + if (method_body_uses.TryGetValue(rva, out var _)) + { + method_body_uses[rva]++; + } + else + { + method_body_uses.Add(rva, 1); + } + } + + do + { + int methodToken2Trim = Convert.ToInt32(line, 16); + int rva2Trim = token_to_rva[methodToken2Trim]; + method_body_uses[rva2Trim]--; + } while ((line = sr.ReadLine()) != null); + + return method_body_uses; + } + + private static void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFilePath, FileStream fs, Dictionary method_body_uses) + { + using (FileStream os = File.Open(trimmedAssemblyFilePath, FileMode.Create)) + { + fs.Position = 0; + MemoryStream memStream = new MemoryStream((int)fs.Length); + fs.CopyTo(memStream); + + foreach (var kvp in method_body_uses) + { + int rva = kvp.Key; + int count = kvp.Value; + if (count == 0) + { + int methodSize = ComputeMethodSize(peReader, rva); + int actualLoc = ComputeMethodHash(peReader, rva); + int headerSize = ComputeMethodHeaderSize(memStream, actualLoc); + ZeroOutMethodBody(ref memStream, methodSize, actualLoc, headerSize); + } + } + + memStream.Position = 0; + memStream.CopyTo(os); + } + } + + private static int ComputeMethodSize(PEReader peReader, int rva) + { + MethodBodyBlock mb = peReader.GetMethodBody(rva); + return mb.Size; + } + + private static int ComputeMethodHash(PEReader peReader, int rva) + { + int sectionIndex = peReader.PEHeaders.GetContainingSectionIndex(rva); + int relativeOffset = rva - peReader.PEHeaders.SectionHeaders[sectionIndex].VirtualAddress; + return (peReader.PEHeaders.SectionHeaders[sectionIndex].PointerToRawData + relativeOffset); + } + + private static int ComputeMethodHeaderSize(MemoryStream memStream, int actualLoc) + { + memStream.Position = actualLoc; + int firstbyte = memStream.ReadByte(); + int headerFlag = firstbyte & 0b11; + return (headerFlag == 2 ? 1 : 4); + } + + private static void ZeroOutMethodBody(ref MemoryStream memStream, int methodSize, int actualLoc, int headerSize) + { + memStream.Position = actualLoc + headerSize; + + byte[] zeroBuffer; + zeroBuffer = ArrayPool.Shared.Rent(methodSize); + Array.Clear(zeroBuffer, 0, zeroBuffer.Length); + memStream.Write(zeroBuffer, 0, methodSize - headerSize); + ArrayPool.Shared.Return(zeroBuffer); + } + + private static void ReplaceAssemblyWithTrimmedOne(string assemblyFilePath, string trimmedAssemblyFilePath) + { + File.Delete(assemblyFilePath); + File.Move(trimmedAssemblyFilePath, assemblyFilePath); + } } From f517e79ff7a913dbe355cf7a5a2971e0103e1a93 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 5 Jun 2023 17:24:57 -0400 Subject: [PATCH 12/27] Update src/tasks/AotCompilerTask/MonoAOTCompiler.cs Co-authored-by: Ankit Jain --- src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 90960edba0162..8d4d2adedd2ed 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -726,7 +726,7 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st { if (string.IsNullOrEmpty(CompiledMethodsOutputPath)) { - Log.LogMessage(MessageImportance.Low, "Skipping collecting the list of aot compiled methods, cause the value of CompiledMethodsOutputPath is empty."); + Log.LogMessage(MessageImportance.Low, $"Skipping collecting the list of aot compiled methods, because the value of {nameof(CompiledMethodsOutputPath)} is empty."); } else { From ae66d5236b05b3129116f42297bb7f34b91d965e Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Mon, 5 Jun 2023 17:53:47 -0400 Subject: [PATCH 13/27] Move parameter validation code --- src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 36 ++++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 8d4d2adedd2ed..47c28c20d44e1 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -161,7 +161,7 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task /// /// Directory to store the aot output when using switch compiled-methods-outfile /// - public string? CompiledMethodsOutputPath { get; set; } + public string? CompiledMethodsOutputDirectory { get; set; } /// /// File to use for profile-guided optimization, *only* the methods described in the file will be AOT compiled. @@ -447,6 +447,17 @@ private bool ProcessAndValidateArguments() throw new LogAsErrorException($"Could not find {fullPath} to AOT"); } + if (CollectCompiledMethods) + { + if (string.IsNullOrEmpty(CompiledMethodsOutputDirectory)) + throw new LogAsErrorException($"{nameof(CompiledMethodsOutputDirectory)} is empty. When {nameof(CollectCompiledMethods)} is set to true, the user needs to provide a directory for {nameof(CompiledMethodsOutputDirectory)}."); + + if (!Directory.Exists(CompiledMethodsOutputDirectory)) + { + Directory.CreateDirectory(CompiledMethodsOutputDirectory); + } + } + return !Log.HasLoggedErrors; } @@ -724,23 +735,12 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st if (CollectCompiledMethods) { - if (string.IsNullOrEmpty(CompiledMethodsOutputPath)) - { - Log.LogMessage(MessageImportance.Low, $"Skipping collecting the list of aot compiled methods, because the value of {nameof(CompiledMethodsOutputPath)} is empty."); - } - else - { - if (!Directory.Exists(CompiledMethodsOutputPath)) - { - Directory.CreateDirectory(CompiledMethodsOutputPath); - } - string assemblyFileName = Path.GetFileName(assembly); - string assemblyName = assemblyFileName.Replace(".", "_"); - string outputFileName = assemblyName + "_compiled_methods.txt"; - string outputFilePath = Path.Combine(CompiledMethodsOutputPath, outputFileName); - aotArgs.Add($"compiled-methods-outfile={outputFilePath}"); - aotAssembly.SetMetadata("MethodTokenFile", outputFilePath); - } + string assemblyFileName = Path.GetFileName(assembly); + string assemblyName = assemblyFileName.Replace(".", "_"); + string outputFileName = assemblyName + "_compiled_methods.txt"; + string outputFilePath = Path.Combine(CompiledMethodsOutputDirectory, outputFileName); + aotArgs.Add($"compiled-methods-outfile={outputFilePath}"); + aotAssembly.SetMetadata("MethodTokenFile", outputFilePath); } // compute output mode and file names From 30306e4bb7da3954e4203b57c94b7a6d2c79fe0a Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 5 Jun 2023 17:54:20 -0400 Subject: [PATCH 14/27] Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 42a0983882fa7..798137eab77e9 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -103,7 +103,7 @@ private bool TrimMethods(ITaskItem assemblyItem) string methodTokenFile = assemblyItem.GetMetadata("MethodTokenFile"); if (!File.Exists(methodTokenFile)) { - Log.LogMessage(MessageImportance.Low, $"[ILStrip] {methodTokenFile} doesn't exit."); + Log.LogMessage(MessageImportance.Low, $"{methodTokenFile} doesn't exist."); return true; } From 56a781ab23bf168ae064ca98fa3c5c98301c7b2f Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 5 Jun 2023 17:55:24 -0400 Subject: [PATCH 15/27] Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 798137eab77e9..bedf3b3066028 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -117,7 +117,7 @@ private bool TrimMethods(ITaskItem assemblyItem) if (!File.Exists(assemblyFilePath)) { - Log.LogMessage(MessageImportance.Low, $"[ILStrip] {assemblyFilePath} doesn't exit."); + Log.LogMessage(MessageImportance.Low, $"{assemblyFilePath} read from {methodTokenFile} doesn't exist."); return true; } From 78981c8e3f777e5079cb21cdb0baad8bf8218d46 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 5 Jun 2023 17:55:51 -0400 Subject: [PATCH 16/27] Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index bedf3b3066028..babf523a9e4cb 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -234,11 +234,7 @@ private static void CreateTrimmedAssembly(PEReader peReader, string trimmedAssem } } - private static int ComputeMethodSize(PEReader peReader, int rva) - { - MethodBodyBlock mb = peReader.GetMethodBody(rva); - return mb.Size; - } + private static int ComputeMethodSize(PEReader peReader, int rva) => peReader.GetMethodBody(rva).Size; private static int ComputeMethodHash(PEReader peReader, int rva) { From b519b4cd7d88691a9beca533c0ebf1c59e5163a7 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:08:07 -0400 Subject: [PATCH 17/27] Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index babf523a9e4cb..3345271c5ec5a 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -107,7 +107,7 @@ private bool TrimMethods(ITaskItem assemblyItem) return true; } - using (StreamReader sr = new StreamReader(methodTokenFile)) + using StreamReader sr = new(methodTokenFile); { string? assemblyFilePath = sr.ReadLine(); if (string.IsNullOrEmpty(assemblyFilePath)) From 3322022deeecaba083814cbebef12f346487fd91 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:08:27 -0400 Subject: [PATCH 18/27] Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 3345271c5ec5a..e11e362575409 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -124,7 +124,7 @@ private bool TrimMethods(ITaskItem assemblyItem) string trimmedAssemblyFilePath = ComputeTrimmedAssemblyPath(assemblyFilePath); bool isTrimmed = false; - using (FileStream fs = File.Open(assemblyFilePath, FileMode.Open)) + using FileStream fs = File.Open(assemblyFilePath, FileMode.Open); { PEReader peReader = new PEReader(fs, PEStreamOptions.LeaveOpen); MetadataReader mr = peReader.GetMetadataReader(); From 1a83902404cc5c6380c46354353659511f4645ce Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:08:44 -0400 Subject: [PATCH 19/27] Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index e11e362575409..bde90fb3094f5 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -126,7 +126,7 @@ private bool TrimMethods(ITaskItem assemblyItem) using FileStream fs = File.Open(assemblyFilePath, FileMode.Open); { - PEReader peReader = new PEReader(fs, PEStreamOptions.LeaveOpen); + using PEReader peReader = new(fs, PEStreamOptions.LeaveOpen); MetadataReader mr = peReader.GetMetadataReader(); string guidValue = ComputeGuid(mr); From f1b2753a59f3ae5240b17c8368caf72907978b68 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:43:40 -0400 Subject: [PATCH 20/27] Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index bde90fb3094f5..7bac0637c7c26 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -177,8 +177,8 @@ private static string ComputeGuid(MetadataReader mr) private static Dictionary ComputeMethodBodyUsage(MetadataReader mr, StreamReader sr, string? line) { - Dictionary token_to_rva = new Dictionary(); - Dictionary method_body_uses = new Dictionary(); + Dictionary token_to_rva = new(); + Dictionary method_body_uses = new(); foreach (MethodDefinitionHandle mdefh in mr.MethodDefinitions) { From 328e9be258c918fa30b512e0a6ea8d9195831db6 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:44:05 -0400 Subject: [PATCH 21/27] Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 7bac0637c7c26..2cbe43917ee72 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -210,7 +210,7 @@ private static Dictionary ComputeMethodBodyUsage(MetadataReader mr, St private static void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFilePath, FileStream fs, Dictionary method_body_uses) { - using (FileStream os = File.Open(trimmedAssemblyFilePath, FileMode.Create)) + using FileStream os = File.Open(trimmedAssemblyFilePath, FileMode.Create); { fs.Position = 0; MemoryStream memStream = new MemoryStream((int)fs.Length); From 10226b7791523bfa7d047bc3d908b1c6640583d5 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Mon, 5 Jun 2023 19:46:11 -0400 Subject: [PATCH 22/27] Add more error handling --- src/mono/sample/HelloWorld/HelloWorld.csproj | 2 +- src/mono/sample/HelloWorld/Makefile | 2 +- src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 10 +++++- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 32 +++++++++++++++---- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/mono/sample/HelloWorld/HelloWorld.csproj b/src/mono/sample/HelloWorld/HelloWorld.csproj index 975b1fd4572ee..3987d235cbaaf 100644 --- a/src/mono/sample/HelloWorld/HelloWorld.csproj +++ b/src/mono/sample/HelloWorld/HelloWorld.csproj @@ -26,7 +26,7 @@ Assemblies="@(AotInputAssemblies)" OutputDir="$(PublishDir)" CollectCompiledMethods="$(StripILCode)" - CompiledMethodsOutputPath="$(MethodTokenFilePath)" + CompiledMethodsOutputDirectory="$(CompiledMethodsOutputDirectory)" IntermediateOutputPath="$(IntermediateOutputPath)" UseAotDataFile="$(UseAotDataFile)" CacheFilePath="$(IntermediateOutputPath)aot_compiler_cache.json" diff --git a/src/mono/sample/HelloWorld/Makefile b/src/mono/sample/HelloWorld/Makefile index f7f31dffdbc6b..5ed26eddddf0e 100644 --- a/src/mono/sample/HelloWorld/Makefile +++ b/src/mono/sample/HelloWorld/Makefile @@ -21,7 +21,7 @@ publish: -r $(TARGET_OS)-$(MONO_ARCH) \ /p:RunAOTCompilation=$(AOT) \ /p:StripILCode=$(StripILCode) \ - /p:MethodTokenFilePath=$(MethodTokenFilePath) \ + /p:CompiledMethodsOutputDirectory=$(CompiledMethodsOutputDirectory) \ '/p:NetTracePath="$(NET_TRACE_PATH)"' \ '/p:PgoBinaryPath="$(PGO_BINARY_PATH)"' \ '/p:MibcProfilePath="$(MIBC_PROFILE_PATH)"' diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 47c28c20d44e1..b6d6e9d14a8da 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -738,7 +738,15 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st string assemblyFileName = Path.GetFileName(assembly); string assemblyName = assemblyFileName.Replace(".", "_"); string outputFileName = assemblyName + "_compiled_methods.txt"; - string outputFilePath = Path.Combine(CompiledMethodsOutputDirectory, outputFileName); + string outputFilePath; + if (string.IsNullOrEmpty(CompiledMethodsOutputDirectory)) + { + outputFilePath = outputFileName; + } + else + { + outputFilePath = Path.Combine(CompiledMethodsOutputDirectory, outputFileName); + } aotArgs.Add($"compiled-methods-outfile={outputFilePath}"); aotAssembly.SetMetadata("MethodTokenFile", outputFilePath); } diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 2cbe43917ee72..8f6aeaf213395 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -101,6 +101,10 @@ private bool StripAssembly(ITaskItem assemblyItem) private bool TrimMethods(ITaskItem assemblyItem) { string methodTokenFile = assemblyItem.GetMetadata("MethodTokenFile"); + if (string.IsNullOrEmpty(methodTokenFile)) + { + Log.LogError($"Metadata MethodTokenFile of {assemblyItem.ItemSpec} is empty"); + } if (!File.Exists(methodTokenFile)) { Log.LogMessage(MessageImportance.Low, $"{methodTokenFile} doesn't exist."); @@ -117,7 +121,7 @@ private bool TrimMethods(ITaskItem assemblyItem) if (!File.Exists(assemblyFilePath)) { - Log.LogMessage(MessageImportance.Low, $"{assemblyFilePath} read from {methodTokenFile} doesn't exist."); + Log.LogError($"{assemblyFilePath} read from {methodTokenFile} doesn't exist."); return true; } @@ -133,7 +137,7 @@ private bool TrimMethods(ITaskItem assemblyItem) string? expectedGuidValue = sr.ReadLine(); if (!string.Equals(guidValue, expectedGuidValue, StringComparison.OrdinalIgnoreCase)) { - Log.LogMessage(MessageImportance.Low, $"[ILStrip] GUID value of {assemblyFilePath} doesn't match the value listed in {methodTokenFile}."); + Log.LogError($"[ILStrip] GUID value of {assemblyFilePath} doesn't match the value listed in {methodTokenFile}."); return true; } @@ -141,7 +145,7 @@ private bool TrimMethods(ITaskItem assemblyItem) if (!string.IsNullOrEmpty(line)) { isTrimmed = true; - Dictionary method_body_uses = ComputeMethodBodyUsage(mr, sr, line); + Dictionary method_body_uses = ComputeMethodBodyUsage(mr, sr, line, methodTokenFile); CreateTrimmedAssembly(peReader, trimmedAssemblyFilePath, fs, method_body_uses); } } @@ -175,7 +179,7 @@ private static string ComputeGuid(MetadataReader mr) return mvid.ToString(); } - private static Dictionary ComputeMethodBodyUsage(MetadataReader mr, StreamReader sr, string? line) + private Dictionary ComputeMethodBodyUsage(MetadataReader mr, StreamReader sr, string? line, string methodTokenFile) { Dictionary token_to_rva = new(); Dictionary method_body_uses = new(); @@ -201,14 +205,24 @@ private static Dictionary ComputeMethodBodyUsage(MetadataReader mr, St do { int methodToken2Trim = Convert.ToInt32(line, 16); - int rva2Trim = token_to_rva[methodToken2Trim]; - method_body_uses[rva2Trim]--; + if (methodToken2Trim <= 0) + { + Log.LogError($"Method token: {line} in {methodTokenFile} is not a valid hex value."); + } + if (token_to_rva.TryGetValue(methodToken2Trim, out int rva2Trim)) + { + method_body_uses[rva2Trim]--; + } + else + { + Log.LogError($"Method token: {line} in {methodTokenFile} can't be found within the assembly."); + } } while ((line = sr.ReadLine()) != null); return method_body_uses; } - private static void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFilePath, FileStream fs, Dictionary method_body_uses) + private void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFilePath, FileStream fs, Dictionary method_body_uses) { using FileStream os = File.Open(trimmedAssemblyFilePath, FileMode.Create); { @@ -227,6 +241,10 @@ private static void CreateTrimmedAssembly(PEReader peReader, string trimmedAssem int headerSize = ComputeMethodHeaderSize(memStream, actualLoc); ZeroOutMethodBody(ref memStream, methodSize, actualLoc, headerSize); } + else if (count < 0) + { + Log.LogError($"Method usage count is less than zero for rva: {rva}."); + } } memStream.Position = 0; From fc088bd783845316ba5d130822f007c4a656db43 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Mon, 12 Jun 2023 15:53:59 -0400 Subject: [PATCH 23/27] Provide a list of trimmed assemblies as output --- src/mono/sample/HelloWorld/HelloWorld.csproj | 7 ++++++ src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 3 +-- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 25 ++++++++++++++++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/mono/sample/HelloWorld/HelloWorld.csproj b/src/mono/sample/HelloWorld/HelloWorld.csproj index 3987d235cbaaf..86d71d64898f7 100644 --- a/src/mono/sample/HelloWorld/HelloWorld.csproj +++ b/src/mono/sample/HelloWorld/HelloWorld.csproj @@ -49,6 +49,13 @@ + + + diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index b6d6e9d14a8da..a762eb8a3266b 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -735,8 +735,7 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st if (CollectCompiledMethods) { - string assemblyFileName = Path.GetFileName(assembly); - string assemblyName = assemblyFileName.Replace(".", "_"); + string assemblyName = assemblyFilename.Replace(".", "_"); string outputFileName = assemblyName + "_compiled_methods.txt"; string outputFilePath; if (string.IsNullOrEmpty(CompiledMethodsOutputDirectory)) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 8f6aeaf213395..176fc947db8ab 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -36,6 +36,17 @@ public class ILStrip : Microsoft.Build.Utilities.Task /// public bool TrimIndividualMethods { get; set; } + /// + /// Assembilies got trimmed successfully. + /// + /// Successful trimming will set the following metadata on the items: + /// - TrimmedAssemblyFileName + /// + [Output] + public ITaskItem[]? TrimmedAssemblies { get; set; } + + private List trimmedAssemblies = new List(); + public override bool Execute() { if (Assemblies.Length == 0) @@ -62,6 +73,11 @@ public override bool Execute() } }); + if (TrimIndividualMethods) + { + TrimmedAssemblies = trimmedAssemblies.ToArray(); + } + if (!result.IsCompleted && !Log.HasLoggedErrors) { Log.LogError("Unknown failure occurred while IL stripping assemblies. Check logs to get more details."); @@ -151,7 +167,7 @@ private bool TrimMethods(ITaskItem assemblyItem) } if (isTrimmed) { - ReplaceAssemblyWithTrimmedOne(assemblyFilePath, trimmedAssemblyFilePath); + AddItemToTrimmedList(assemblyFilePath, trimmedAssemblyFilePath); } } @@ -280,9 +296,10 @@ private static void ZeroOutMethodBody(ref MemoryStream memStream, int methodSize ArrayPool.Shared.Return(zeroBuffer); } - private static void ReplaceAssemblyWithTrimmedOne(string assemblyFilePath, string trimmedAssemblyFilePath) + private void AddItemToTrimmedList(string assemblyFilePath, string trimmedAssemblyFilePath) { - File.Delete(assemblyFilePath); - File.Move(trimmedAssemblyFilePath, assemblyFilePath); + var trimmedAssemblyItem = new TaskItem(assemblyFilePath); + trimmedAssemblyItem.SetMetadata("TrimmedAssemblyFileName", trimmedAssemblyFilePath); + trimmedAssemblies.Add(trimmedAssemblyItem); } } From 3aad84ab20958e2834fc7cde15b3ad792c1d0ab1 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Tue, 13 Jun 2023 11:59:10 -0400 Subject: [PATCH 24/27] Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index 176fc947db8ab..d5ad94b0ad774 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -45,7 +45,7 @@ public class ILStrip : Microsoft.Build.Utilities.Task [Output] public ITaskItem[]? TrimmedAssemblies { get; set; } - private List trimmedAssemblies = new List(); + private readonly List _trimmedAssemblies = new(); public override bool Execute() { From 91803d99c03506fea7d03f5749eeb914422500b8 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Tue, 13 Jun 2023 15:07:18 -0400 Subject: [PATCH 25/27] Address coding style feedbacks --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 97 +++++++++---------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index d5ad94b0ad774..f095d94bbeed4 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -120,55 +120,52 @@ private bool TrimMethods(ITaskItem assemblyItem) if (string.IsNullOrEmpty(methodTokenFile)) { Log.LogError($"Metadata MethodTokenFile of {assemblyItem.ItemSpec} is empty"); + return true; } if (!File.Exists(methodTokenFile)) { - Log.LogMessage(MessageImportance.Low, $"{methodTokenFile} doesn't exist."); + Log.LogError($"{methodTokenFile} doesn't exist."); return true; } using StreamReader sr = new(methodTokenFile); + string? assemblyFilePath = sr.ReadLine(); + if (string.IsNullOrEmpty(assemblyFilePath)) { - string? assemblyFilePath = sr.ReadLine(); - if (string.IsNullOrEmpty(assemblyFilePath)) - { - return true; - } - - if (!File.Exists(assemblyFilePath)) - { - Log.LogError($"{assemblyFilePath} read from {methodTokenFile} doesn't exist."); - return true; - } + Log.LogError($"The first line of {assemblyFilePath} is empty."); + return true; + } - string trimmedAssemblyFilePath = ComputeTrimmedAssemblyPath(assemblyFilePath); - bool isTrimmed = false; + if (!File.Exists(assemblyFilePath)) + { + Log.LogError($"{assemblyFilePath} read from {methodTokenFile} doesn't exist."); + return true; + } - using FileStream fs = File.Open(assemblyFilePath, FileMode.Open); - { - using PEReader peReader = new(fs, PEStreamOptions.LeaveOpen); - MetadataReader mr = peReader.GetMetadataReader(); + string trimmedAssemblyFilePath = ComputeTrimmedAssemblyPath(assemblyFilePath); + bool isTrimmed = false; + using FileStream fs = File.Open(assemblyFilePath, FileMode.Open); + using PEReader peReader = new(fs, PEStreamOptions.LeaveOpen); + MetadataReader mr = peReader.GetMetadataReader(); + string guidValue = ComputeGuid(mr); + string? expectedGuidValue = sr.ReadLine(); + if (!string.Equals(guidValue, expectedGuidValue, StringComparison.OrdinalIgnoreCase)) + { + Log.LogError($"[ILStrip] GUID value of {assemblyFilePath} doesn't match the value listed in {methodTokenFile}."); + return true; + } - string guidValue = ComputeGuid(mr); - string? expectedGuidValue = sr.ReadLine(); - if (!string.Equals(guidValue, expectedGuidValue, StringComparison.OrdinalIgnoreCase)) - { - Log.LogError($"[ILStrip] GUID value of {assemblyFilePath} doesn't match the value listed in {methodTokenFile}."); - return true; - } + string? line = sr.ReadLine(); + if (!string.IsNullOrEmpty(line)) + { + isTrimmed = true; + Dictionary methodBodyUses = ComputeMethodBodyUsage(mr, sr, line, methodTokenFile); + CreateTrimmedAssembly(peReader, trimmedAssemblyFilePath, fs, methodBodyUses); + } - string? line = sr.ReadLine(); - if (!string.IsNullOrEmpty(line)) - { - isTrimmed = true; - Dictionary method_body_uses = ComputeMethodBodyUsage(mr, sr, line, methodTokenFile); - CreateTrimmedAssembly(peReader, trimmedAssemblyFilePath, fs, method_body_uses); - } - } - if (isTrimmed) - { - AddItemToTrimmedList(assemblyFilePath, trimmedAssemblyFilePath); - } + if (isTrimmed) + { + AddItemToTrimmedList(assemblyFilePath, trimmedAssemblyFilePath); } return true; @@ -180,11 +177,11 @@ private static string ComputeTrimmedAssemblyPath(string assemblyFilePath) string? assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath); if (string.IsNullOrEmpty(assemblyPath)) { - return (assemblyName + "_new.dll"); + return (assemblyName + "_trimmed.dll"); } else { - return Path.Combine(assemblyPath, (assemblyName + "_new.dll")); + return Path.Combine(assemblyPath, (assemblyName + "_trimmed.dll")); } } @@ -197,8 +194,8 @@ private static string ComputeGuid(MetadataReader mr) private Dictionary ComputeMethodBodyUsage(MetadataReader mr, StreamReader sr, string? line, string methodTokenFile) { - Dictionary token_to_rva = new(); - Dictionary method_body_uses = new(); + Dictionary tokenToRva = new(); + Dictionary methodBodyUses = new(); foreach (MethodDefinitionHandle mdefh in mr.MethodDefinitions) { @@ -206,15 +203,15 @@ private Dictionary ComputeMethodBodyUsage(MetadataReader mr, StreamRea MethodDefinition mdef = mr.GetMethodDefinition(mdefh); int rva = mdef.RelativeVirtualAddress; - token_to_rva.Add(methodToken, rva); + tokenToRva.Add(methodToken, rva); - if (method_body_uses.TryGetValue(rva, out var _)) + if (methodBodyUses.TryGetValue(rva, out var _)) { - method_body_uses[rva]++; + methodBodyUses[rva]++; } else { - method_body_uses.Add(rva, 1); + methodBodyUses.Add(rva, 1); } } @@ -225,9 +222,9 @@ private Dictionary ComputeMethodBodyUsage(MetadataReader mr, StreamRea { Log.LogError($"Method token: {line} in {methodTokenFile} is not a valid hex value."); } - if (token_to_rva.TryGetValue(methodToken2Trim, out int rva2Trim)) + if (tokenToRva.TryGetValue(methodToken2Trim, out int rva2Trim)) { - method_body_uses[rva2Trim]--; + methodBodyUses[rva2Trim]--; } else { @@ -235,10 +232,10 @@ private Dictionary ComputeMethodBodyUsage(MetadataReader mr, StreamRea } } while ((line = sr.ReadLine()) != null); - return method_body_uses; + return methodBodyUses; } - private void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFilePath, FileStream fs, Dictionary method_body_uses) + private void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFilePath, FileStream fs, Dictionary methodBodyUses) { using FileStream os = File.Open(trimmedAssemblyFilePath, FileMode.Create); { @@ -246,7 +243,7 @@ private void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFile MemoryStream memStream = new MemoryStream((int)fs.Length); fs.CopyTo(memStream); - foreach (var kvp in method_body_uses) + foreach (var kvp in methodBodyUses) { int rva = kvp.Key; int count = kvp.Value; From 8cb9621be3c87758e5b12c56ffbc9c5ceef02da3 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Tue, 13 Jun 2023 17:27:26 -0400 Subject: [PATCH 26/27] Fix var anmes --- src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs index f095d94bbeed4..34c81b67f54e4 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs @@ -75,7 +75,7 @@ public override bool Execute() if (TrimIndividualMethods) { - TrimmedAssemblies = trimmedAssemblies.ToArray(); + TrimmedAssemblies = _trimmedAssemblies.ToArray(); } if (!result.IsCompleted && !Log.HasLoggedErrors) @@ -147,9 +147,9 @@ private bool TrimMethods(ITaskItem assemblyItem) using FileStream fs = File.Open(assemblyFilePath, FileMode.Open); using PEReader peReader = new(fs, PEStreamOptions.LeaveOpen); MetadataReader mr = peReader.GetMetadataReader(); - string guidValue = ComputeGuid(mr); + string actualGuidValue = ComputeGuid(mr); string? expectedGuidValue = sr.ReadLine(); - if (!string.Equals(guidValue, expectedGuidValue, StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(actualGuidValue, expectedGuidValue, StringComparison.OrdinalIgnoreCase)) { Log.LogError($"[ILStrip] GUID value of {assemblyFilePath} doesn't match the value listed in {methodTokenFile}."); return true; @@ -297,6 +297,6 @@ private void AddItemToTrimmedList(string assemblyFilePath, string trimmedAssembl { var trimmedAssemblyItem = new TaskItem(assemblyFilePath); trimmedAssemblyItem.SetMetadata("TrimmedAssemblyFileName", trimmedAssemblyFilePath); - trimmedAssemblies.Add(trimmedAssemblyItem); + _trimmedAssemblies.Add(trimmedAssemblyItem); } } From ee2b37fc011bf83700fbb7dd8ed11c73eaab0f53 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Thu, 15 Jun 2023 15:32:09 -0400 Subject: [PATCH 27/27] Delete trimmed assemblies after copy --- src/mono/sample/HelloWorld/HelloWorld.csproj | 1 + src/mono/sample/HelloWorld/Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mono/sample/HelloWorld/HelloWorld.csproj b/src/mono/sample/HelloWorld/HelloWorld.csproj index 86d71d64898f7..bc6db3770c040 100644 --- a/src/mono/sample/HelloWorld/HelloWorld.csproj +++ b/src/mono/sample/HelloWorld/HelloWorld.csproj @@ -57,5 +57,6 @@ DestinationFiles="@(TrimmedAssemblies)" OverwriteReadOnlyFiles="true" /> + diff --git a/src/mono/sample/HelloWorld/Makefile b/src/mono/sample/HelloWorld/Makefile index 5ed26eddddf0e..8441e565d29c5 100644 --- a/src/mono/sample/HelloWorld/Makefile +++ b/src/mono/sample/HelloWorld/Makefile @@ -7,7 +7,7 @@ MONO_ARCH?=$(shell . $(TOP)eng/native/init-os-and-arch.sh && echo $${arch}) TARGET_OS?=$(shell . $(TOP)eng/native/init-os-and-arch.sh && echo $${os}) AOT?=false StripILCode?=false -MethodTokenFilePath?= # +CompiledMethodsOutputDirectory?= # #NET_TRACE_PATH= #PGO_BINARY_PATH=