From 441d4d4544fc5d72a6578d747a226b46ba07d14c Mon Sep 17 00:00:00 2001 From: Stephen Hawley Date: Thu, 15 Jun 2023 15:52:08 -0400 Subject: [PATCH 1/8] Integrate class handle rewriting into static registrar process. --- dotnet/targets/Xamarin.Shared.Sdk.targets | 1 + .../Tasks/ClassRedirectorTask.cs | 134 ------------------ .../Xamarin.MacDev.Tasks.csproj | 3 + msbuild/Xamarin.Shared/Xamarin.Shared.targets | 1 + tools/common/Application.cs | 25 +++- tools/common/Driver.cs | 2 +- .../Tasks => tools/common}/Rewriter.cs | 47 +++--- tools/common/StaticRegistrar.cs | 23 ++- tools/dotnet-linker/LinkerConfiguration.cs | 3 + tools/dotnet-linker/Steps/RegistrarStep.cs | 2 +- tools/dotnet-linker/dotnet-linker.csproj | 3 + tools/mmp/driver.cs | 6 +- tools/mmp/mmp.csproj | 3 + tools/mtouch/BuildTasks.mtouch.cs | 7 +- tools/mtouch/mtouch.csproj | 3 + 15 files changed, 90 insertions(+), 173 deletions(-) delete mode 100644 msbuild/Xamarin.MacDev.Tasks/Tasks/ClassRedirectorTask.cs rename {msbuild/Xamarin.MacDev.Tasks/Tasks => tools/common}/Rewriter.cs (89%) diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets index 8515abdfba33..0ac82794330a 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.targets +++ b/dotnet/targets/Xamarin.Shared.Sdk.targets @@ -504,6 +504,7 @@ @(_MonoLibrary -> 'MonoLibrary=%(Identity)') MtouchFloat32=$(MtouchFloat32) Optimize=$(_BundlerOptimize) + OptimizeClassHandles=$(OptimizeClassHandles) PartialStaticRegistrarLibrary=$(_LibPartialStaticRegistrar) Platform=$(_PlatformName) PlatformAssembly=$(_PlatformAssemblyName).dll diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/ClassRedirectorTask.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/ClassRedirectorTask.cs deleted file mode 100644 index 799d615dd40a..000000000000 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/ClassRedirectorTask.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml.Linq; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; -using ClassRedirector; - -using Xamarin.Messaging.Build.Client; - -#nullable enable - -namespace Xamarin.MacDev.Tasks { - public class ClassRedirector : XamarinTask, ITaskCallback { - [Required] - public string InputDirectory { get; set; } = string.Empty; - - [Required] - public string OutputDirectory { get; set; } = string.Empty; - - [Required] - public ITaskItem? ClassMapPath { get; set; } - - [Required] - public string PlatformAssembly { get; set; } = string.Empty; - - public override bool Execute () - { - if (ShouldExecuteRemotely ()) { - var taskRunner = new TaskRunner (SessionId, BuildEngine4); - return taskRunner.RunAsync (this).Result; - } - - return ExecuteLocally (); - } - - public IEnumerable GetAdditionalItemsToBeCopied () - { - if (!Directory.Exists (InputDirectory)) - return Enumerable.Empty (); - - return Directory.GetFiles (InputDirectory, "*", SearchOption.AllDirectories) - .Select (f => new TaskItem (f)); - } - - public bool ShouldCopyToBuildServer (ITaskItem item) => true; - - public bool ShouldCreateOutputFile (ITaskItem item) => true; - - bool ExecuteLocally () - { - if (!Directory.Exists (InputDirectory)) { - Log.LogError ($"InputDirectory {InputDirectory} doesn't exist."); - return false; - } - - if (InputDirectory == OutputDirectory) { - Log.LogError ($"OutputDirectory {OutputDirectory} must be difference from InputDirectory."); - return false; - } - - if (!Directory.Exists (OutputDirectory)) { - try { - Directory.CreateDirectory (OutputDirectory); - } catch (Exception directoryException) { - Log.LogErrorFromException (directoryException); - } - } - - if (!DirectoryIsWritable (OutputDirectory)) { - Log.LogError ($"OutputDirectory {OutputDirectory} is not writable."); - return false; - } - - var classMapPath = ClassMapPath!.ItemSpec; - if (!File.Exists (classMapPath)) { - Log.LogError ($"ClassMapPath file {classMapPath} does not exist."); - return false; - } - - var xamarinDll = PlatformAssembly; - - if (!File.Exists (xamarinDll)) - xamarinDll = Path.Combine (InputDirectory, PlatformAssembly); - - if (!File.Exists (xamarinDll)) { - Log.LogError ($"PlatformAssembly {PlatformAssembly} does not exist as is or in {InputDirectory}"); - return false; - } - - - - var dllsToProcess = CollectDlls (InputDirectory); - - var map = ReadRegistrarFile (classMapPath); - - try { - Log.LogMessage (MessageImportance.Low, $"Redirecting class_handle usage from directory {InputDirectory} in the following dlls: {string.Join (",", dllsToProcess)}"); - Log.LogMessage (MessageImportance.Low, $"Redirecting class_handle usage with the platform dll {xamarinDll}"); - Log.LogMessage (MessageImportance.Low, $"Redirecting class_handle usage with the following {nameof (ClassMapPath)}: {classMapPath}"); - var rewriter = new Rewriter (map, xamarinDll, dllsToProcess, OutputDirectory); - rewriter.Process (); - } catch (Exception e) { - Log.LogErrorFromException (e); - return false; - } - - return true; - } - - static bool DirectoryIsWritable (string path) - { - var info = new DirectoryInfo (path); - return !info.Attributes.HasFlag (FileAttributes.ReadOnly); - } - - static string [] CollectDlls (string dir) - { - return Directory.GetFiles (dir, "*.dll"); // GetFiles returns full paths - } - - static CSToObjCMap ReadRegistrarFile (string path) - { - var doc = XDocument.Load (path); - var map = CSToObjCMap.FromXDocument (doc); - if (map is null) - throw new Exception ($"Unable to read static registrar map file {path}"); - return map; - } - } -} - diff --git a/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj b/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj index fd654702bedb..a7bc0e26861c 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj +++ b/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj @@ -78,6 +78,9 @@ external\ObjCNameIndex.cs + + external\ObjCNameIndex.cs + diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index 88cb81a60ea4..b4d6caf1c3de 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -1838,6 +1838,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. NoDSymUtil="$(NoDSymUtil)" PackageDebugSymbols="$(PackageDebugSymbols)" Registrar="$(Registrar)" + OptimizeClassHandles="$(OptimizeClassHandles)" Verbosity="$(_BundlerVerbosity)" > diff --git a/tools/common/Application.cs b/tools/common/Application.cs index 8a2f12ca72a6..e308dbbf612e 100644 --- a/tools/common/Application.cs +++ b/tools/common/Application.cs @@ -18,6 +18,8 @@ using ObjCRuntime; +using ClassRedirector; + #if MONOTOUCH using PlatformResolver = MonoTouch.Tuner.MonoTouchResolver; #elif MMP @@ -167,7 +169,7 @@ public bool IsDefaultMarshalManagedExceptionMode { public bool EnableBitCode { get { return BitCodeMode != BitCodeMode.None; } } public bool SkipMarkingNSObjectsInUserAssemblies { get; set; } - public string ClassMapPath = ""; + public bool OptimizeClassHandles { get; set; } = false; // assembly_build_targets describes what kind of native code each assembly should be compiled into for mobile targets (iOS, tvOS, watchOS). // An assembly can be compiled into: static object (.o), dynamic library (.dylib) or a framework (.framework). @@ -1029,10 +1031,23 @@ public void RunRegistrar () } #endif var registrar = new Registrar.StaticRegistrar (this); - if (RootAssemblies.Count == 1) - registrar.GenerateSingleAssembly (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, Path.GetFileNameWithoutExtension (RootAssembly), out var _, ClassMapPath); - else - registrar.Generate (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, out var _, ClassMapPath); + if (RootAssemblies.Count == 1) { + registrar.GenerateSingleAssembly (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, Path.GetFileNameWithoutExtension (RootAssembly), out var _, out var oneAssemblyMap); + if (OptimizeClassHandles) { + RewriteClassHandles (oneAssemblyMap, resolvedAssemblies.Values); + } + } else { + registrar.Generate (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, out var _, out var typeMap); + if (OptimizeClassHandles) { + RewriteClassHandles (typeMap, resolvedAssemblies.Values); + } + } + } + + void RewriteClassHandles (CSToObjCMap map, IEnumerable assemblies) + { + var rewriter = new Rewriter (map, assemblies); + rewriter.Process (); } public IEnumerable Abis { diff --git a/tools/common/Driver.cs b/tools/common/Driver.cs index e2af63788031..b286bfb72e69 100644 --- a/tools/common/Driver.cs +++ b/tools/common/Driver.cs @@ -257,7 +257,7 @@ static bool ParseOptions (Application app, Mono.Options.OptionSet options, strin options.Add ("skip-marking-nsobjects-in-user-assemblies:", "Don't mark NSObject (and any subclass of NSObject) in user assemblies in the linker. This may break your app, use at own risk.", v => { app.SkipMarkingNSObjectsInUserAssemblies = ParseBool (v, "--skip-marking-nsobjects-in-user-assemblies"); }); - options.Add ("class-map-path=", "Sets the path for an output path to generate a class map XML file used to optimize class handle access when the static registrar has been used.", v => { app.ClassMapPath = v; }); + options.Add ("optimitize-class-handles", "Optimizes usage for class handles to static references instead of pinvokes.", v => { app.OptimizeClassHandles = ParseBool (v, "--optimitize-class-handles"); }); // Keep the ResponseFileSource option at the end. diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/Rewriter.cs b/tools/common/Rewriter.cs similarity index 89% rename from msbuild/Xamarin.MacDev.Tasks/Tasks/Rewriter.cs rename to tools/common/Rewriter.cs index eb573ba1f080..293aaadb7e16 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/Rewriter.cs +++ b/tools/common/Rewriter.cs @@ -8,7 +8,7 @@ #nullable enable -namespace Xamarin.MacDev.Tasks { +namespace ClassRedirector { public class Rewriter { const string runtimeName = "ObjCRuntime.Runtime"; const string classHandleName = "ObjCRuntime.Runtime/ClassHandles"; @@ -18,18 +18,23 @@ public class Rewriter { const string classPtrName = "class_ptr"; CSToObjCMap map; string pathToXamarinAssembly; - string [] assembliesToPatch; - string outputDirectory; - SimpleAssemblyResolver resolver; + string? outputDirectory = null; Dictionary csTypeToFieldDef = new Dictionary (); + IEnumerable assemblies; + AssemblyDefinition xamarinAssembly; - public Rewriter (CSToObjCMap map, string pathToXamarinAssembly, string [] assembliesToPatch, string outputDirectory) + public Rewriter (CSToObjCMap map, IEnumerable assembliesToPatch) { this.map = map; - this.pathToXamarinAssembly = pathToXamarinAssembly; - this.assembliesToPatch = assembliesToPatch; - this.outputDirectory = outputDirectory; - resolver = new SimpleAssemblyResolver (assembliesToPatch); + this.assemblies = assembliesToPatch; + var xasm = assembliesToPatch.Select (assem => assem.MainModule).FirstOrDefault (ContainsNativeHandle)?.Assembly; + if (xasm is null) { + throw new Exception ("Unable to find Xamarin assembly."); + } else { + xamarinAssembly = xasm; + pathToXamarinAssembly = xamarinAssembly.MainModule.FileName; + } + } public void Process () @@ -41,8 +46,7 @@ public void Process () Dictionary CreateClassHandles () { var classMap = new Dictionary (); - using var assemblyStm = new FileStream (pathToXamarinAssembly, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); - using var module = ModuleDefinition.ReadModule (assemblyStm); + var module = xamarinAssembly.MainModule; var classHandles = LocateClassHandles (module); if (classHandles is null) @@ -58,7 +62,7 @@ Dictionary CreateClassHandles () if (mtClassMapDef is null) throw new Exception ($"Unable to find {mtClassMapName} in {pathToXamarinAssembly}"); - var nativeHandle = module.Types.FirstOrDefault (t => t.FullName == nativeHandleName); + var nativeHandle = LocateNativeHandle (module); if (nativeHandle is null) throw new Exception ($"Unable to find {nativeHandleName} in {pathToXamarinAssembly}"); @@ -74,7 +78,7 @@ Dictionary CreateClassHandles () classMap [csName] = fieldDef; } - module.Write (ToOutputFileName (pathToXamarinAssembly)); + module.Write (); return classMap; } @@ -124,6 +128,16 @@ FieldDefinition AddPublicStaticField (TypeDefinition inType, string fieldName, T return fieldDef; } + bool ContainsNativeHandle (ModuleDefinition module) + { + return LocateNativeHandle (module) is not null; + } + + TypeDefinition? LocateNativeHandle (ModuleDefinition module) + { + return AllTypes (module).FirstOrDefault (t => t.FullName == nativeHandleName); + } + TypeDefinition? LocateClassHandles (ModuleDefinition module) { return AllTypes (module).FirstOrDefault (t => t.FullName == classHandleName); @@ -136,11 +150,10 @@ FieldDefinition AddPublicStaticField (TypeDefinition inType, string fieldName, T void PatchClassPtrUsage (Dictionary classMap) { - foreach (var path in assembliesToPatch) { - using var stm = new FileStream (path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); - using var module = ModuleDefinition.ReadModule (stm); + foreach (var assem in assemblies) { + var module = assem.MainModule; PatchClassPtrUsage (classMap, module); - module.Write (ToOutputFileName (path)); + module.Write (); } } diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index 47d8172de8a7..f7dde0e6049c 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -2843,7 +2843,7 @@ public string GetInitializationMethodName (string single_assembly) } } - void Specialize (AutoIndentStringBuilder sb, out string initialization_method, string type_map_path) + void Specialize (AutoIndentStringBuilder sb, out string initialization_method, out CSToObjCMap typeMap) { List exceptions = new List (); List skip = new List (); @@ -3296,10 +3296,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method, s sb.WriteLine (map.ToString ()); sb.WriteLine (map_init.ToString ()); - if (!string.IsNullOrEmpty (type_map_path)) { - var doc = CSToObjCMap.ToXDocument (map_dict); - doc.Save (type_map_path); - } + typeMap = map_dict; ErrorHelper.ThrowIfErrors (exceptions); } @@ -5504,24 +5501,24 @@ public void FilterTrimmedApi (AnnotationStore annotations) } } - public void GenerateSingleAssembly (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, string assembly, out string initialization_method, string type_map_path) + public void GenerateSingleAssembly (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, string assembly, out string initialization_method, out CSToObjCMap typeMap) { single_assembly = assembly; - Generate (resolver, assemblies, header_path, source_path, out initialization_method, type_map_path); + Generate (resolver, assemblies, header_path, source_path, out initialization_method, out typeMap); } - public void Generate (IEnumerable assemblies, string header_path, string source_path, out string initialization_method, string type_map_path) + public void Generate (IEnumerable assemblies, string header_path, string source_path, out string initialization_method, out CSToObjCMap typeMap) { - Generate (null, assemblies, header_path, source_path, out initialization_method, type_map_path); + Generate (null, assemblies, header_path, source_path, out initialization_method, out typeMap); } - public void Generate (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, out string initialization_method, string type_map_path) + public void Generate (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, out string initialization_method, out CSToObjCMap typeMap) { Register (resolver, assemblies); - Generate (header_path, source_path, out initialization_method, type_map_path); + Generate (header_path, source_path, out initialization_method, out typeMap); } - public void Generate (string header_path, string source_path, out string initialization_method, string type_map_path) + public void Generate (string header_path, string source_path, out string initialization_method) { var sb = new AutoIndentStringBuilder (); header = new AutoIndentStringBuilder (); @@ -5556,7 +5553,7 @@ public void Generate (string header_path, string source_path, out string initial if (App.Embeddinator) methods.WriteLine ("void xamarin_embeddinator_initialize ();"); - Specialize (sb, out initialization_method, type_map_path); + Specialize (sb, out initialization_method, out var typeMap); methods.WriteLine (); methods.AppendLine (); diff --git a/tools/dotnet-linker/LinkerConfiguration.cs b/tools/dotnet-linker/LinkerConfiguration.cs index 3ce2760d5487..9cac29469a10 100644 --- a/tools/dotnet-linker/LinkerConfiguration.cs +++ b/tools/dotnet-linker/LinkerConfiguration.cs @@ -224,6 +224,9 @@ public static LinkerConfiguration GetInstance (LinkContext context) case "Optimize": user_optimize_flags = value; break; + case "OptimizeClassHandles": + Application.OptimizeClassHandles = true; + break; case "PartialStaticRegistrarLibrary": PartialStaticRegistrarLibrary = value; break; diff --git a/tools/dotnet-linker/Steps/RegistrarStep.cs b/tools/dotnet-linker/Steps/RegistrarStep.cs index dd6f8795d9a7..53871a4ea253 100644 --- a/tools/dotnet-linker/Steps/RegistrarStep.cs +++ b/tools/dotnet-linker/Steps/RegistrarStep.cs @@ -42,7 +42,7 @@ protected override void TryEndProcess () // so we need to remove those that were later trimmed away by the trimmer. Configuration.Target.StaticRegistrar.FilterTrimmedApi (Annotations); } - Configuration.Target.StaticRegistrar.Generate (header, code, out var initialization_method, app.ClassMapPath); + Configuration.Target.StaticRegistrar.Generate (header, code, out var initialization_method); var items = new List (); foreach (var abi in Configuration.Abis) { diff --git a/tools/dotnet-linker/dotnet-linker.csproj b/tools/dotnet-linker/dotnet-linker.csproj index e4d84b61fd44..66ff6ea83c1a 100644 --- a/tools/dotnet-linker/dotnet-linker.csproj +++ b/tools/dotnet-linker/dotnet-linker.csproj @@ -107,6 +107,9 @@ tools\common\CSToObjCMap.cs + + tools\common\Rewriter.cs + tools\common\ObjCNameIndex.cs diff --git a/tools/mmp/driver.cs b/tools/mmp/driver.cs index 74a982c0791d..dadbdff8c2df 100644 --- a/tools/mmp/driver.cs +++ b/tools/mmp/driver.cs @@ -794,7 +794,11 @@ static void Compile () if (App.Registrar == RegistrarMode.Static) { registrarPath = Path.Combine (App.Cache.Location, "registrar.m"); var registrarH = Path.Combine (App.Cache.Location, "registrar.h"); - BuildTarget.StaticRegistrar.Generate (BuildTarget.Resolver.ResolverCache.Values, registrarH, registrarPath, out initialization_method, App.ClassMapPath); + BuildTarget.StaticRegistrar.Generate (BuildTarget.Resolver.ResolverCache.Values, registrarH, registrarPath, out initialization_method, out var typeMap); + if (App.OptimizeClassHandles) { + var rewriter = new Rewriter (BuildTarget.Resolver.ResolverCache.Values, typeMap); + rewriter.Process (); + } var platform_assembly = BuildTarget.Resolver.ResolverCache.First ((v) => v.Value.Name.Name == BuildTarget.StaticRegistrar.PlatformAssembly).Value; Frameworks.Gather (App, platform_assembly, BuildTarget.Frameworks, BuildTarget.WeakFrameworks); diff --git a/tools/mmp/mmp.csproj b/tools/mmp/mmp.csproj index c72abec43d49..e3725497a7d2 100644 --- a/tools/mmp/mmp.csproj +++ b/tools/mmp/mmp.csproj @@ -364,6 +364,9 @@ tools\common\CSToObjCMap.cs + + tools\common\Rewriter.cs + tools\common\ObjCNameIndex.cs diff --git a/tools/mtouch/BuildTasks.mtouch.cs b/tools/mtouch/BuildTasks.mtouch.cs index fed490c8e3d4..206a5196eed6 100644 --- a/tools/mtouch/BuildTasks.mtouch.cs +++ b/tools/mtouch/BuildTasks.mtouch.cs @@ -120,8 +120,13 @@ public override IEnumerable Outputs { protected override void Execute () { - Target.StaticRegistrar.Generate (Target.Assemblies.Select ((a) => a.AssemblyDefinition), RegistrarHeaderPath, RegistrarCodePath, out var initialization_name, Target.App.ClassMapPath); + var assemblies = Target.Assemblies.Select ((a) => a.AssemblyDefinition); + Target.StaticRegistrar.Generate (assemblies, RegistrarHeaderPath, RegistrarCodePath, out var initialization_name, out var typeMap); RegistrationMethods.Add (initialization_name); + if (Target.App.OptimizeClassHandles) { + var rewriter = new Rewriter (assemblies, typeMap); + rewriter.Process (); + } } } diff --git a/tools/mtouch/mtouch.csproj b/tools/mtouch/mtouch.csproj index 7c99af4f9ac9..64051977bb12 100644 --- a/tools/mtouch/mtouch.csproj +++ b/tools/mtouch/mtouch.csproj @@ -338,6 +338,9 @@ tools\common\OSPlatformAttributeExtensions.cs + + tools\common\Rewriter.cs + tools\common\CSToObjCMap.cs From 4a395e2e9be06af05b85ea30f8e596726f6d5985 Mon Sep 17 00:00:00 2001 From: GitHub Actions Autoformatter Date: Thu, 15 Jun 2023 20:04:54 +0000 Subject: [PATCH 2/8] Auto-format source code --- tools/common/Rewriter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/common/Rewriter.cs b/tools/common/Rewriter.cs index 293aaadb7e16..7451f974be79 100644 --- a/tools/common/Rewriter.cs +++ b/tools/common/Rewriter.cs @@ -34,7 +34,7 @@ public Rewriter (CSToObjCMap map, IEnumerable assembliesToPa xamarinAssembly = xasm; pathToXamarinAssembly = xamarinAssembly.MainModule.FileName; } - + } public void Process () From 487445663cc92a8d2478ad2630fcca673657885d Mon Sep 17 00:00:00 2001 From: Stephen Hawley Date: Fri, 16 Jun 2023 15:00:08 -0400 Subject: [PATCH 3/8] make suggested changes --- dotnet/targets/Xamarin.Shared.Sdk.targets | 1 - .../Xamarin.MacDev.Tasks.csproj | 9 -------- msbuild/Xamarin.Shared/Xamarin.Shared.targets | 1 - tools/common/Application.cs | 17 ++------------ tools/common/Driver.cs | 2 -- tools/common/Optimizations.cs | 7 ++++++ tools/common/StaticRegistrar.cs | 23 +++++++++++-------- tools/dotnet-linker/LinkerConfiguration.cs | 3 --- tools/dotnet-linker/Steps/RegistrarStep.cs | 2 +- tools/mmp/driver.cs | 7 ++---- tools/mtouch/BuildTasks.mtouch.cs | 7 ++---- 11 files changed, 27 insertions(+), 52 deletions(-) diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets index 0ac82794330a..8515abdfba33 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.targets +++ b/dotnet/targets/Xamarin.Shared.Sdk.targets @@ -504,7 +504,6 @@ @(_MonoLibrary -> 'MonoLibrary=%(Identity)') MtouchFloat32=$(MtouchFloat32) Optimize=$(_BundlerOptimize) - OptimizeClassHandles=$(OptimizeClassHandles) PartialStaticRegistrarLibrary=$(_LibPartialStaticRegistrar) Platform=$(_PlatformName) PlatformAssembly=$(_PlatformAssemblyName).dll diff --git a/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj b/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj index a7bc0e26861c..15085fc0124e 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj +++ b/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj @@ -72,15 +72,6 @@ external\SdkVersions.cs - - external\CSToObjCMap.cs - - - external\ObjCNameIndex.cs - - - external\ObjCNameIndex.cs - diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index b4d6caf1c3de..88cb81a60ea4 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -1838,7 +1838,6 @@ Copyright (C) 2018 Microsoft. All rights reserved. NoDSymUtil="$(NoDSymUtil)" PackageDebugSymbols="$(PackageDebugSymbols)" Registrar="$(Registrar)" - OptimizeClassHandles="$(OptimizeClassHandles)" Verbosity="$(_BundlerVerbosity)" > diff --git a/tools/common/Application.cs b/tools/common/Application.cs index e308dbbf612e..ababfc99d264 100644 --- a/tools/common/Application.cs +++ b/tools/common/Application.cs @@ -169,7 +169,6 @@ public bool IsDefaultMarshalManagedExceptionMode { public bool EnableBitCode { get { return BitCodeMode != BitCodeMode.None; } } public bool SkipMarkingNSObjectsInUserAssemblies { get; set; } - public bool OptimizeClassHandles { get; set; } = false; // assembly_build_targets describes what kind of native code each assembly should be compiled into for mobile targets (iOS, tvOS, watchOS). // An assembly can be compiled into: static object (.o), dynamic library (.dylib) or a framework (.framework). @@ -1032,24 +1031,12 @@ public void RunRegistrar () #endif var registrar = new Registrar.StaticRegistrar (this); if (RootAssemblies.Count == 1) { - registrar.GenerateSingleAssembly (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, Path.GetFileNameWithoutExtension (RootAssembly), out var _, out var oneAssemblyMap); - if (OptimizeClassHandles) { - RewriteClassHandles (oneAssemblyMap, resolvedAssemblies.Values); - } + registrar.GenerateSingleAssembly (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, Path.GetFileNameWithoutExtension (RootAssembly), out var _, Optimizations.RedirectClassHandlesSafe); } else { - registrar.Generate (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, out var _, out var typeMap); - if (OptimizeClassHandles) { - RewriteClassHandles (typeMap, resolvedAssemblies.Values); - } + registrar.Generate (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, out var _, Optimizations.RedirectClassHandlesSafe); } } - void RewriteClassHandles (CSToObjCMap map, IEnumerable assemblies) - { - var rewriter = new Rewriter (map, assemblies); - rewriter.Process (); - } - public IEnumerable Abis { get { return abis; } set { abis = new List (value); } diff --git a/tools/common/Driver.cs b/tools/common/Driver.cs index b286bfb72e69..a06336644acf 100644 --- a/tools/common/Driver.cs +++ b/tools/common/Driver.cs @@ -257,8 +257,6 @@ static bool ParseOptions (Application app, Mono.Options.OptionSet options, strin options.Add ("skip-marking-nsobjects-in-user-assemblies:", "Don't mark NSObject (and any subclass of NSObject) in user assemblies in the linker. This may break your app, use at own risk.", v => { app.SkipMarkingNSObjectsInUserAssemblies = ParseBool (v, "--skip-marking-nsobjects-in-user-assemblies"); }); - options.Add ("optimitize-class-handles", "Optimizes usage for class handles to static references instead of pinvokes.", v => { app.OptimizeClassHandles = ParseBool (v, "--optimitize-class-handles"); }); - // Keep the ResponseFileSource option at the end. options.Add (new Mono.Options.ResponseFileSource ()); diff --git a/tools/common/Optimizations.cs b/tools/common/Optimizations.cs index ca6a7af6119d..7ae93ca69e56 100644 --- a/tools/common/Optimizations.cs +++ b/tools/common/Optimizations.cs @@ -163,6 +163,13 @@ public bool? RedirectClassHandles { set { values [(int) Opt.RedirectClassHandles] = value; } } + public bool RedirectClassHandlesSafe { + get { + var redirect = RedirectClassHandles; + return redirect.HasValue && redirect.Value; + } + } + public Optimizations () { values = new bool? [opt_names.Length]; diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index f7dde0e6049c..b77f9c3652e7 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -2843,7 +2843,7 @@ public string GetInitializationMethodName (string single_assembly) } } - void Specialize (AutoIndentStringBuilder sb, out string initialization_method, out CSToObjCMap typeMap) + void Specialize (AutoIndentStringBuilder sb, out string initialization_method, bool rewriteClassHandles) { List exceptions = new List (); List skip = new List (); @@ -3296,7 +3296,10 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method, o sb.WriteLine (map.ToString ()); sb.WriteLine (map_init.ToString ()); - typeMap = map_dict; + if (rewriteClassHandles) { + var rewriter = new Rewriter (map_dict, GetAssemblies ()); + rewriter.Process (); + } ErrorHelper.ThrowIfErrors (exceptions); } @@ -5501,24 +5504,24 @@ public void FilterTrimmedApi (AnnotationStore annotations) } } - public void GenerateSingleAssembly (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, string assembly, out string initialization_method, out CSToObjCMap typeMap) + public void GenerateSingleAssembly (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, string assembly, out string initialization_method, bool rewriteClassHandles) { single_assembly = assembly; - Generate (resolver, assemblies, header_path, source_path, out initialization_method, out typeMap); + Generate (resolver, assemblies, header_path, source_path, out initialization_method, rewriteClassHandles); } - public void Generate (IEnumerable assemblies, string header_path, string source_path, out string initialization_method, out CSToObjCMap typeMap) + public void Generate (IEnumerable assemblies, string header_path, string source_path, out string initialization_method, bool rewriteClassHandles) { - Generate (null, assemblies, header_path, source_path, out initialization_method, out typeMap); + Generate (null, assemblies, header_path, source_path, out initialization_method, rewriteClassHandles); } - public void Generate (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, out string initialization_method, out CSToObjCMap typeMap) + public void Generate (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, out string initialization_method, bool rewriteClassHandles) { Register (resolver, assemblies); - Generate (header_path, source_path, out initialization_method, out typeMap); + Generate (header_path, source_path, out initialization_method, rewriteClassHandles); } - public void Generate (string header_path, string source_path, out string initialization_method) + public void Generate (string header_path, string source_path, out string initialization_method, bool rewriteClassHandles) { var sb = new AutoIndentStringBuilder (); header = new AutoIndentStringBuilder (); @@ -5553,7 +5556,7 @@ public void Generate (string header_path, string source_path, out string initial if (App.Embeddinator) methods.WriteLine ("void xamarin_embeddinator_initialize ();"); - Specialize (sb, out initialization_method, out var typeMap); + Specialize (sb, out initialization_method, rewriteClassHandles); methods.WriteLine (); methods.AppendLine (); diff --git a/tools/dotnet-linker/LinkerConfiguration.cs b/tools/dotnet-linker/LinkerConfiguration.cs index 9cac29469a10..3ce2760d5487 100644 --- a/tools/dotnet-linker/LinkerConfiguration.cs +++ b/tools/dotnet-linker/LinkerConfiguration.cs @@ -224,9 +224,6 @@ public static LinkerConfiguration GetInstance (LinkContext context) case "Optimize": user_optimize_flags = value; break; - case "OptimizeClassHandles": - Application.OptimizeClassHandles = true; - break; case "PartialStaticRegistrarLibrary": PartialStaticRegistrarLibrary = value; break; diff --git a/tools/dotnet-linker/Steps/RegistrarStep.cs b/tools/dotnet-linker/Steps/RegistrarStep.cs index 53871a4ea253..43d6b902081d 100644 --- a/tools/dotnet-linker/Steps/RegistrarStep.cs +++ b/tools/dotnet-linker/Steps/RegistrarStep.cs @@ -42,7 +42,7 @@ protected override void TryEndProcess () // so we need to remove those that were later trimmed away by the trimmer. Configuration.Target.StaticRegistrar.FilterTrimmedApi (Annotations); } - Configuration.Target.StaticRegistrar.Generate (header, code, out var initialization_method); + Configuration.Target.StaticRegistrar.Generate (header, code, out var initialization_method, app.Optimizations.RedirectClassHandlesSafe); var items = new List (); foreach (var abi in Configuration.Abis) { diff --git a/tools/mmp/driver.cs b/tools/mmp/driver.cs index dadbdff8c2df..e7de9f18c46c 100644 --- a/tools/mmp/driver.cs +++ b/tools/mmp/driver.cs @@ -49,6 +49,7 @@ using Xamarin.Utils; using Xamarin.Linker; using Registrar; +using ClassRedirector; using ObjCRuntime; namespace Xamarin.Bundler { @@ -794,11 +795,7 @@ static void Compile () if (App.Registrar == RegistrarMode.Static) { registrarPath = Path.Combine (App.Cache.Location, "registrar.m"); var registrarH = Path.Combine (App.Cache.Location, "registrar.h"); - BuildTarget.StaticRegistrar.Generate (BuildTarget.Resolver.ResolverCache.Values, registrarH, registrarPath, out initialization_method, out var typeMap); - if (App.OptimizeClassHandles) { - var rewriter = new Rewriter (BuildTarget.Resolver.ResolverCache.Values, typeMap); - rewriter.Process (); - } + BuildTarget.StaticRegistrar.Generate (BuildTarget.Resolver.ResolverCache.Values, registrarH, registrarPath, out initialization_method, App.Optimizations.RedirectClassHandlesSafe); var platform_assembly = BuildTarget.Resolver.ResolverCache.First ((v) => v.Value.Name.Name == BuildTarget.StaticRegistrar.PlatformAssembly).Value; Frameworks.Gather (App, platform_assembly, BuildTarget.Frameworks, BuildTarget.WeakFrameworks); diff --git a/tools/mtouch/BuildTasks.mtouch.cs b/tools/mtouch/BuildTasks.mtouch.cs index 206a5196eed6..4a29b953e380 100644 --- a/tools/mtouch/BuildTasks.mtouch.cs +++ b/tools/mtouch/BuildTasks.mtouch.cs @@ -7,6 +7,7 @@ using Xamarin.MacDev; using Xamarin.Utils; +using ClassRedirector; namespace Xamarin.Bundler { public abstract class ProcessTask : BuildTask { @@ -121,12 +122,8 @@ public override IEnumerable Outputs { protected override void Execute () { var assemblies = Target.Assemblies.Select ((a) => a.AssemblyDefinition); - Target.StaticRegistrar.Generate (assemblies, RegistrarHeaderPath, RegistrarCodePath, out var initialization_name, out var typeMap); + Target.StaticRegistrar.Generate (assemblies, RegistrarHeaderPath, RegistrarCodePath, out var initialization_name, Target.App.Optimizations.RedirectClassHandlesSafe); RegistrationMethods.Add (initialization_name); - if (Target.App.OptimizeClassHandles) { - var rewriter = new Rewriter (assemblies, typeMap); - rewriter.Process (); - } } } From 8fd0b1b5324c4cfef12e8e6d13fdf7c2011c5f82 Mon Sep 17 00:00:00 2001 From: Stephen Hawley Date: Mon, 19 Jun 2023 10:56:08 -0400 Subject: [PATCH 4/8] simplify, simplify, simplify --- tools/common/Application.cs | 4 +-- tools/common/CSToObjCMap.cs | 37 ---------------------- tools/common/ObjCNameIndex.cs | 21 ------------ tools/common/Optimizations.cs | 7 ---- tools/common/Rewriter.cs | 2 ++ tools/common/StaticRegistrar.cs | 24 +++++++------- tools/dotnet-linker/Steps/RegistrarStep.cs | 2 +- tools/mmp/driver.cs | 2 +- tools/mtouch/BuildTasks.mtouch.cs | 2 +- 9 files changed, 19 insertions(+), 82 deletions(-) diff --git a/tools/common/Application.cs b/tools/common/Application.cs index ababfc99d264..dfdff4cd3cf6 100644 --- a/tools/common/Application.cs +++ b/tools/common/Application.cs @@ -1031,9 +1031,9 @@ public void RunRegistrar () #endif var registrar = new Registrar.StaticRegistrar (this); if (RootAssemblies.Count == 1) { - registrar.GenerateSingleAssembly (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, Path.GetFileNameWithoutExtension (RootAssembly), out var _, Optimizations.RedirectClassHandlesSafe); + registrar.GenerateSingleAssembly (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, Path.GetFileNameWithoutExtension (RootAssembly), out var _); } else { - registrar.Generate (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, out var _, Optimizations.RedirectClassHandlesSafe); + registrar.Generate (resolver, resolvedAssemblies.Values, Path.ChangeExtension (registrar_m, "h"), registrar_m, out var _); } } diff --git a/tools/common/CSToObjCMap.cs b/tools/common/CSToObjCMap.cs index e98a929dfced..2d3f5cf77c70 100644 --- a/tools/common/CSToObjCMap.cs +++ b/tools/common/CSToObjCMap.cs @@ -7,46 +7,9 @@ namespace ClassRedirector { public class CSToObjCMap : Dictionary { - const string objMapName = "CSToObjCMap"; - const string elementName = "Element"; - const string csNameName = "CSName"; public CSToObjCMap () : base () { } - - public static XElement ToXElement (CSToObjCMap map) - { - return new XElement (objMapName, Elements (map)); - } - - static IEnumerable Elements (CSToObjCMap map) - { - return map.Select (kvp => new XElement (elementName, new XAttribute (csNameName, kvp.Key), ObjCNameIndex.ToXElement (kvp.Value))); - } - - public static CSToObjCMap FromXElement (XElement xmap) - { - var map = new CSToObjCMap (); - var elements = from el in xmap.Descendants (elementName) - select new KeyValuePair (el.Attribute (csNameName)?.Value, - ObjCNameIndex.FromXElement (el.Element (ObjCNameIndex.ObjNameIndexName))); - foreach (var elem in elements) { - if (elem.Key is not null && elem.Value is not null) - map.Add (elem.Key, elem.Value); - } - return map; - } - - public static CSToObjCMap? FromXDocument (XDocument doc) - { - var el = doc.Descendants (objMapName).FirstOrDefault (); - return el is null ? null : FromXElement (el); - } - - public static XDocument ToXDocument (CSToObjCMap map) - { - return new XDocument (ToXElement (map)); - } } } diff --git a/tools/common/ObjCNameIndex.cs b/tools/common/ObjCNameIndex.cs index cac09237722b..3b26891de46b 100644 --- a/tools/common/ObjCNameIndex.cs +++ b/tools/common/ObjCNameIndex.cs @@ -6,9 +6,6 @@ namespace ClassRedirector { public class ObjCNameIndex { - public const string ObjNameIndexName = "ObjNameIndex"; - const string nameName = "Name"; - const string indexName = "Index"; public ObjCNameIndex (string objCName, int mapIndex) { ObjCName = objCName; @@ -16,24 +13,6 @@ public ObjCNameIndex (string objCName, int mapIndex) } public string ObjCName { get; private set; } public int MapIndex { get; private set; } - - public static XElement ToXElement (ObjCNameIndex nameIndex) - { - return new XElement (ObjNameIndexName, - new XElement (nameName, nameIndex.ObjCName), - new XElement (indexName, nameIndex.MapIndex)); - } - - public static ObjCNameIndex? FromXElement (XElement? objNameIndex) - { - if (objNameIndex is null) - return null; - var name = (string?) objNameIndex.Element (nameName); - var index = (int?) objNameIndex.Element (indexName); - if (name is null || index is null) - return null; - return new ObjCNameIndex (name, index.Value); - } } } diff --git a/tools/common/Optimizations.cs b/tools/common/Optimizations.cs index 7ae93ca69e56..ca6a7af6119d 100644 --- a/tools/common/Optimizations.cs +++ b/tools/common/Optimizations.cs @@ -163,13 +163,6 @@ public bool? RedirectClassHandles { set { values [(int) Opt.RedirectClassHandles] = value; } } - public bool RedirectClassHandlesSafe { - get { - var redirect = RedirectClassHandles; - return redirect.HasValue && redirect.Value; - } - } - public Optimizations () { values = new bool? [opt_names.Length]; diff --git a/tools/common/Rewriter.cs b/tools/common/Rewriter.cs index 7451f974be79..e3d85212eb65 100644 --- a/tools/common/Rewriter.cs +++ b/tools/common/Rewriter.cs @@ -9,6 +9,7 @@ #nullable enable namespace ClassRedirector { +#if NET public class Rewriter { const string runtimeName = "ObjCRuntime.Runtime"; const string classHandleName = "ObjCRuntime.Runtime/ClassHandles"; @@ -305,5 +306,6 @@ string ToOutputFileName (string pathToInputFileName) return Path.Combine (outputDirectory, Path.GetFileName (pathToInputFileName)); } } +#endif } diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index b77f9c3652e7..d16c9e9edfb2 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -2843,7 +2843,7 @@ public string GetInitializationMethodName (string single_assembly) } } - void Specialize (AutoIndentStringBuilder sb, out string initialization_method, bool rewriteClassHandles) + void Specialize (AutoIndentStringBuilder sb, out string initialization_method) { List exceptions = new List (); List skip = new List (); @@ -3295,12 +3295,12 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method, b sb.WriteLine (map.ToString ()); sb.WriteLine (map_init.ToString ()); - - if (rewriteClassHandles) { +#if NET + if (App.Optimizations.RedirectClassHandles == true) { var rewriter = new Rewriter (map_dict, GetAssemblies ()); rewriter.Process (); } - +#endif ErrorHelper.ThrowIfErrors (exceptions); } @@ -5504,24 +5504,24 @@ public void FilterTrimmedApi (AnnotationStore annotations) } } - public void GenerateSingleAssembly (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, string assembly, out string initialization_method, bool rewriteClassHandles) + public void GenerateSingleAssembly (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, string assembly, out string initialization_method) { single_assembly = assembly; - Generate (resolver, assemblies, header_path, source_path, out initialization_method, rewriteClassHandles); + Generate (resolver, assemblies, header_path, source_path, out initialization_method); } - public void Generate (IEnumerable assemblies, string header_path, string source_path, out string initialization_method, bool rewriteClassHandles) + public void Generate (IEnumerable assemblies, string header_path, string source_path, out string initialization_method) { - Generate (null, assemblies, header_path, source_path, out initialization_method, rewriteClassHandles); + Generate (null, assemblies, header_path, source_path, out initialization_method); } - public void Generate (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, out string initialization_method, bool rewriteClassHandles) + public void Generate (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, out string initialization_method) { Register (resolver, assemblies); - Generate (header_path, source_path, out initialization_method, rewriteClassHandles); + Generate (header_path, source_path, out initialization_method); } - public void Generate (string header_path, string source_path, out string initialization_method, bool rewriteClassHandles) + public void Generate (string header_path, string source_path, out string initialization_method) { var sb = new AutoIndentStringBuilder (); header = new AutoIndentStringBuilder (); @@ -5556,7 +5556,7 @@ public void Generate (string header_path, string source_path, out string initial if (App.Embeddinator) methods.WriteLine ("void xamarin_embeddinator_initialize ();"); - Specialize (sb, out initialization_method, rewriteClassHandles); + Specialize (sb, out initialization_method); methods.WriteLine (); methods.AppendLine (); diff --git a/tools/dotnet-linker/Steps/RegistrarStep.cs b/tools/dotnet-linker/Steps/RegistrarStep.cs index 43d6b902081d..53871a4ea253 100644 --- a/tools/dotnet-linker/Steps/RegistrarStep.cs +++ b/tools/dotnet-linker/Steps/RegistrarStep.cs @@ -42,7 +42,7 @@ protected override void TryEndProcess () // so we need to remove those that were later trimmed away by the trimmer. Configuration.Target.StaticRegistrar.FilterTrimmedApi (Annotations); } - Configuration.Target.StaticRegistrar.Generate (header, code, out var initialization_method, app.Optimizations.RedirectClassHandlesSafe); + Configuration.Target.StaticRegistrar.Generate (header, code, out var initialization_method); var items = new List (); foreach (var abi in Configuration.Abis) { diff --git a/tools/mmp/driver.cs b/tools/mmp/driver.cs index e7de9f18c46c..2c8d9768e120 100644 --- a/tools/mmp/driver.cs +++ b/tools/mmp/driver.cs @@ -795,7 +795,7 @@ static void Compile () if (App.Registrar == RegistrarMode.Static) { registrarPath = Path.Combine (App.Cache.Location, "registrar.m"); var registrarH = Path.Combine (App.Cache.Location, "registrar.h"); - BuildTarget.StaticRegistrar.Generate (BuildTarget.Resolver.ResolverCache.Values, registrarH, registrarPath, out initialization_method, App.Optimizations.RedirectClassHandlesSafe); + BuildTarget.StaticRegistrar.Generate (BuildTarget.Resolver.ResolverCache.Values, registrarH, registrarPath, out initialization_method); var platform_assembly = BuildTarget.Resolver.ResolverCache.First ((v) => v.Value.Name.Name == BuildTarget.StaticRegistrar.PlatformAssembly).Value; Frameworks.Gather (App, platform_assembly, BuildTarget.Frameworks, BuildTarget.WeakFrameworks); diff --git a/tools/mtouch/BuildTasks.mtouch.cs b/tools/mtouch/BuildTasks.mtouch.cs index 4a29b953e380..e97524445c06 100644 --- a/tools/mtouch/BuildTasks.mtouch.cs +++ b/tools/mtouch/BuildTasks.mtouch.cs @@ -122,7 +122,7 @@ public override IEnumerable Outputs { protected override void Execute () { var assemblies = Target.Assemblies.Select ((a) => a.AssemblyDefinition); - Target.StaticRegistrar.Generate (assemblies, RegistrarHeaderPath, RegistrarCodePath, out var initialization_name, Target.App.Optimizations.RedirectClassHandlesSafe); + Target.StaticRegistrar.Generate (assemblies, RegistrarHeaderPath, RegistrarCodePath, out var initialization_name); RegistrationMethods.Add (initialization_name); } } From f32876a951b16865cb572d520ec49851ea26414c Mon Sep 17 00:00:00 2001 From: Stephen Hawley Date: Mon, 19 Jun 2023 12:12:40 -0400 Subject: [PATCH 5/8] Use the linker context --- tools/common/Rewriter.cs | 36 ++++++++++++++++++++++++++++----- tools/common/StaticRegistrar.cs | 2 +- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/tools/common/Rewriter.cs b/tools/common/Rewriter.cs index e3d85212eb65..b3ecffdbf4ec 100644 --- a/tools/common/Rewriter.cs +++ b/tools/common/Rewriter.cs @@ -5,6 +5,7 @@ using Mono.Cecil; using Mono.Cecil.Cil; using ClassRedirector; +using Mono.Linker; #nullable enable @@ -23,8 +24,9 @@ public class Rewriter { Dictionary csTypeToFieldDef = new Dictionary (); IEnumerable assemblies; AssemblyDefinition xamarinAssembly; + Xamarin.Tuner.DerivedLinkContext linkContext; - public Rewriter (CSToObjCMap map, IEnumerable assembliesToPatch) + public Rewriter (CSToObjCMap map, IEnumerable assembliesToPatch, Xamarin.Tuner.DerivedLinkContext? linkContext) { this.map = map; this.assemblies = assembliesToPatch; @@ -35,6 +37,11 @@ public Rewriter (CSToObjCMap map, IEnumerable assembliesToPa xamarinAssembly = xasm; pathToXamarinAssembly = xamarinAssembly.MainModule.FileName; } + if (linkContext is null) { + throw new Exception ("Rewriter needs a valid link context."); + } else { + this.linkContext = linkContext; + } } @@ -71,6 +78,9 @@ Dictionary CreateClassHandles () if (nativeHandleOpImplicit is null) throw new Exception ($"Unable to find implicit cast in {nativeHandleName}"); + if (map.Count () == 0) + return classMap; + foreach (var nameIndexPair in map) { var csName = nameIndexPair.Key; var nameIndex = nameIndexPair.Value; @@ -79,7 +89,7 @@ Dictionary CreateClassHandles () classMap [csName] = fieldDef; } - module.Write (); + MarkForSave (xamarinAssembly); return classMap; } @@ -153,18 +163,26 @@ void PatchClassPtrUsage (Dictionary classMap) { foreach (var assem in assemblies) { var module = assem.MainModule; - PatchClassPtrUsage (classMap, module); - module.Write (); + if (PatchClassPtrUsage (classMap, module)) { + MarkForSave (assem); + } } } - void PatchClassPtrUsage (Dictionary classMap, ModuleDefinition module) + // returns true if the assembly was changed. + bool PatchClassPtrUsage (Dictionary classMap, ModuleDefinition module) { + var dirty = false; foreach (var cl in AllTypes (module)) { if (classMap.TryGetValue (cl.FullName, out var classPtrField)) { + dirty = true; + // if this doesn't throw, it will + // always change the contents of an + // assembly PatchClassPtrUsage (cl, classPtrField); } } + return dirty; } void PatchClassPtrUsage (TypeDefinition cl, FieldDefinition classPtrField) @@ -305,6 +323,14 @@ string ToOutputFileName (string pathToInputFileName) { return Path.Combine (outputDirectory, Path.GetFileName (pathToInputFileName)); } + + void MarkForSave (AssemblyDefinition assembly) + { + var annotations = linkContext.Annotations; + var action = annotations.GetAction (assembly); + if (action == AssemblyAction.Copy) + annotations.SetAction (assembly, AssemblyAction.Save); + } } #endif } diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index d16c9e9edfb2..cabf085e6a79 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -3297,7 +3297,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) sb.WriteLine (map_init.ToString ()); #if NET if (App.Optimizations.RedirectClassHandles == true) { - var rewriter = new Rewriter (map_dict, GetAssemblies ()); + var rewriter = new Rewriter (map_dict, GetAssemblies (), LinkContext); rewriter.Process (); } #endif From 712115b1d0c63efc001574033717c2f45eb53e97 Mon Sep 17 00:00:00 2001 From: Stephen Hawley Date: Tue, 20 Jun 2023 14:28:37 -0400 Subject: [PATCH 6/8] Fix failing test, improve handling of errors somewhat. --- src/ObjCRuntime/Runtime.cs | 1 + tools/common/Rewriter.cs | 21 +++++++++++++++------ tools/common/StaticRegistrar.cs | 5 ++++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs index f411a851b93e..520e48851722 100644 --- a/src/ObjCRuntime/Runtime.cs +++ b/src/ObjCRuntime/Runtime.cs @@ -206,6 +206,7 @@ public bool IsSimulator { internal static unsafe InitializationOptions* options; #if NET + [Preserve (AllMembers = true)] public static class ClassHandles { internal static unsafe void InitializeClassHandles (MTClassMap* map) diff --git a/tools/common/Rewriter.cs b/tools/common/Rewriter.cs index b3ecffdbf4ec..b9cd49713f5c 100644 --- a/tools/common/Rewriter.cs +++ b/tools/common/Rewriter.cs @@ -45,10 +45,18 @@ public Rewriter (CSToObjCMap map, IEnumerable assembliesToPa } - public void Process () + public string Process () { - var classMap = CreateClassHandles (); + Dictionary classMap; + try { + classMap = CreateClassHandles (); + } catch (Exception e) { + // if this throws, no changes are made to the assemblies + // so it's safe to log it on the far side. + return e.Message; + } PatchClassPtrUsage (classMap); + return ""; } Dictionary CreateClassHandles () @@ -57,8 +65,9 @@ Dictionary CreateClassHandles () var module = xamarinAssembly.MainModule; var classHandles = LocateClassHandles (module); - if (classHandles is null) - throw new Exception ($"Unable to find {classHandleName} type in {pathToXamarinAssembly}"); + if (classHandles is null) { + throw new Exception ($"Unable to find {classHandleName} type in Module {module.Name} File {module.FileName}, assembly {xamarinAssembly.Name}"); + } var initMethod = classHandles.Methods.FirstOrDefault (m => m.Name == initClassHandlesName); if (initMethod is null) @@ -68,11 +77,11 @@ Dictionary CreateClassHandles () var mtClassMapDef = LocateMTClassMap (module); if (mtClassMapDef is null) - throw new Exception ($"Unable to find {mtClassMapName} in {pathToXamarinAssembly}"); + throw new Exception ($"Unable to find {mtClassMapName} in Module {module.Name} File {module.FileName}, assembly {xamarinAssembly.Name}"); var nativeHandle = LocateNativeHandle (module); if (nativeHandle is null) - throw new Exception ($"Unable to find {nativeHandleName} in {pathToXamarinAssembly}"); + throw new Exception ($"Unable to find {nativeHandleName} in Module {module.Name} File {module.FileName}, assembly {xamarinAssembly.Name}"); var nativeHandleOpImplicit = FindOpImplicit (nativeHandle); if (nativeHandleOpImplicit is null) diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index cabf085e6a79..6ce1973a8d9c 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -3298,7 +3298,10 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) #if NET if (App.Optimizations.RedirectClassHandles == true) { var rewriter = new Rewriter (map_dict, GetAssemblies (), LinkContext); - rewriter.Process (); + var result = rewriter.Process (); + if (!string.IsNullOrEmpty (result)) { + Driver.Log (5, $"Not redirecting class handles because {result}"); + } } #endif ErrorHelper.ThrowIfErrors (exceptions); From 2442bdfd516de692c2b1ef686b7ce7b9405d76ad Mon Sep 17 00:00:00 2001 From: Stephen Hawley Date: Wed, 21 Jun 2023 10:27:42 -0400 Subject: [PATCH 7/8] initialize all the things --- src/ObjCRuntime/Runtime.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs index 520e48851722..6024458f9493 100644 --- a/src/ObjCRuntime/Runtime.cs +++ b/src/ObjCRuntime/Runtime.cs @@ -303,6 +303,12 @@ unsafe static void Initialize (InitializationOptions* options) throw ErrorHelper.CreateError (8010, msg); } +#if NET + if (options->RegistrationMap is not null && options->RegistrationMap->map is not null) { + ClassHandles.InitializeClassHandles (options->RegistrationMap->map); + } +#endif + IntPtrEqualityComparer = new IntPtrEqualityComparer (); TypeEqualityComparer = new TypeEqualityComparer (); From 51a9207f9e4ec8bfd3137f89e95c2760c409279a Mon Sep 17 00:00:00 2001 From: Stephen Hawley Date: Thu, 22 Jun 2023 10:30:46 -0400 Subject: [PATCH 8/8] unpreserve preserve --- src/ObjCRuntime/Runtime.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs index 6024458f9493..34916f7e1611 100644 --- a/src/ObjCRuntime/Runtime.cs +++ b/src/ObjCRuntime/Runtime.cs @@ -206,7 +206,6 @@ public bool IsSimulator { internal static unsafe InitializationOptions* options; #if NET - [Preserve (AllMembers = true)] public static class ClassHandles { internal static unsafe void InitializeClassHandles (MTClassMap* map)