From a0bb9db7ad4261f392ed6420e2667a5806ec90a9 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Wed, 5 Sep 2018 11:01:27 +0200 Subject: [PATCH 1/7] [mtouch] add --interp-mixed option When enabling this option, mtouch will AOT compile `mscorlib.dll`. At runtime that means every method that wasn't AOT'd will be executed by the runtime interpreter. --- msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs | 6 ++++++ .../Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props | 1 + .../Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets | 1 + tests/xharness/Jenkins.cs | 3 +++ tools/common/Application.cs | 1 + tools/mtouch/Application.cs | 5 +++-- tools/mtouch/Assembly.cs | 5 +++++ tools/mtouch/Target.cs | 7 ++++++- tools/mtouch/mtouch.cs | 10 +++++++--- 9 files changed, 33 insertions(+), 6 deletions(-) diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs index c0159bc5bc34..1cd724b8ee82 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs +++ b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs @@ -109,6 +109,9 @@ public GccOptions () [Required] public bool UseInterpreter { get; set; } + [Required] + public bool UseInterpreterMixed { get; set; } + [Required] public bool LinkerDumpDependencies { get; set; } @@ -408,6 +411,9 @@ protected override string GenerateCommandLineCommands () if (UseInterpreter) args.Add ("--interpreter"); + if (UseInterpreterMixed) + args.Add ("--interp-mixed"); + switch (LinkMode.ToLowerInvariant ()) { case "sdkonly": args.AddLine ("--linksdkonly"); break; case "none": args.AddLine ("--nolink"); break; diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props index de1f2acdf112..91bd8e3e05bf 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props +++ b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props @@ -52,6 +52,7 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved. $(MSBuildProjectDirectory) False False + False 2 true diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets index db613f01c062..8aa48a931e2c 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets +++ b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets @@ -832,6 +832,7 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved. EnableBitcode="$(MtouchEnableBitcode)" EnableSGenConc="$(MtouchEnableSGenConc)" UseInterpreter="$(MtouchUseInterpreter)" + UseInterpreterMixed="$(MtouchUseInterpreterMixed)" AppExtensionReferences="@(_ResolvedAppExtensionReferences)" ArchiveSymbols="$(MonoSymbolArchive)" Verbosity="$(MtouchVerbosity)" diff --git a/tests/xharness/Jenkins.cs b/tests/xharness/Jenkins.cs index 88829b54dd89..4793b132bc38 100644 --- a/tests/xharness/Jenkins.cs +++ b/tests/xharness/Jenkins.cs @@ -182,12 +182,15 @@ IEnumerable GetTestData (RunTestTask test) yield return new TestData { Variation = "Release (all optimizations)", MTouchExtraArgs = "--registrar:static --optimize:all", Debug = false, Profiling = false, Defines = "OPTIMIZEALL" }; yield return new TestData { Variation = "Debug (all optimizations)", MTouchExtraArgs = "--registrar:static --optimize:all", Debug = true, Profiling = false, Defines = "OPTIMIZEALL" }; yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, Ignored = true, }; + yield return new TestData { Variation = "Debug (interp-mixed)", MTouchExtraArgs = "--interp-mixed", Debug = true, Profiling = false, Ignored = true, }; break; case "mscorlib": yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, Ignored = true, Undefines = "FULL_AOT_RUNTIME" }; + yield return new TestData { Variation = "Debug (interp-mixed)", MTouchExtraArgs = "--interp-mixed", Debug = true, Profiling = false, Ignored = true, Undefines = "FULL_AOT_RUNTIME" }; break; case "mini": yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, Undefines = "FULL_AOT_RUNTIME" }; + yield return new TestData { Variation = "Debug (interp-mixed)", MTouchExtraArgs = "--interp-mixed", Debug = true, Profiling = false, Undefines = "FULL_AOT_RUNTIME" }; break; } break; diff --git a/tools/common/Application.cs b/tools/common/Application.cs index 01b661a2b4d0..6611a7048ec6 100644 --- a/tools/common/Application.cs +++ b/tools/common/Application.cs @@ -64,6 +64,7 @@ public partial class Application public bool? EnableCoopGC; public bool EnableSGenConc; public bool UseInterpreter; + public bool UseInterpreterMixed; public MarshalObjectiveCExceptionMode MarshalObjectiveCExceptions; public MarshalManagedExceptionMode MarshalManagedExceptions; diff --git a/tools/mtouch/Application.cs b/tools/mtouch/Application.cs index 3827c9deeb41..c0b10b481e4f 100644 --- a/tools/mtouch/Application.cs +++ b/tools/mtouch/Application.cs @@ -462,7 +462,7 @@ public bool UseDlsym (string assembly) if (EnableLLVMOnlyBitCode) return false; - if (UseInterpreter) + if (UseInterpreter || UseInterpreterMixed) return true; switch (Platform) { @@ -2124,7 +2124,8 @@ public void StripNativeCode () public void BundleAssemblies () { - var strip = !UseInterpreter && ManagedStrip && IsDeviceBuild && !EnableDebug && !PackageManagedDebugSymbols; + /* TODO: must be more fine-grained for UseInterpreterMixed case */ + var strip = !UseInterpreter && !UseInterpreterMixed && ManagedStrip && IsDeviceBuild && !EnableDebug && !PackageManagedDebugSymbols; var grouped = Targets.SelectMany ((Target t) => t.Assemblies).GroupBy ((Assembly asm) => asm.Identity); foreach (var @group in grouped) { diff --git a/tools/mtouch/Assembly.cs b/tools/mtouch/Assembly.cs index e7618983ada0..09d358495f86 100644 --- a/tools/mtouch/Assembly.cs +++ b/tools/mtouch/Assembly.cs @@ -58,6 +58,11 @@ public bool IsAOTCompiled { /* interpreter only requires a few stubs that are attached * to mscorlib.dll, other assemblies won't be AOT compiled */ return FileName == "mscorlib.dll"; + if (App.UseInterpreterMixed) + /* TODO: for now, only (fully) AOT compile mscorlib.dll. We + * need an additional option to drive what assemblies + * should be AOT compiled */ + return FileName == "mscorlib.dll"; return true; } } diff --git a/tools/mtouch/Target.cs b/tools/mtouch/Target.cs index 75585bd4394d..f9e89de9af0a 100644 --- a/tools/mtouch/Target.cs +++ b/tools/mtouch/Target.cs @@ -1136,6 +1136,11 @@ void AOTCompile () if (App.UseInterpreter) return; + if (App.UseInterpreterMixed) + /* TODO: not sure? we might have to continue here, depending on + * the set of assemblies are AOT'd? */ + return; + // Code in one assembly (either in a P/Invoke or a third-party library) can depend on a third-party library in another assembly. // This means that we must always build assemblies only when all their dependent assemblies have been built, so that // we can link (natively) with the frameworks/dylibs for those dependent assemblies. @@ -1484,7 +1489,7 @@ public void NativeLink (BuildTasks build_tasks) } } - if (App.UseInterpreter) { + if (App.UseInterpreter || App.UseInterpreterMixed) { string libinterp = Path.Combine (libdir, "libmono-ee-interp.a"); linker_flags.AddLinkWith (libinterp); string libicalltable = Path.Combine (libdir, "libmono-icall-table.a"); diff --git a/tools/mtouch/mtouch.cs b/tools/mtouch/mtouch.cs index 983bc6a64f5e..2edf3a08a4de 100644 --- a/tools/mtouch/mtouch.cs +++ b/tools/mtouch/mtouch.cs @@ -456,6 +456,7 @@ public static string GetAotArguments (Application app, string filename, Abi abi, bool enable_debug_symbols = app.PackageManagedDebugSymbols; bool llvm_only = app.EnableLLVMOnlyBitCode; bool interp = app.UseInterpreter; + bool interp_mixed = app.UseInterpreterMixed; bool is32bit = (abi & Abi.Arch32Mask) > 0; string arch = abi.AsArchString (); @@ -476,6 +477,8 @@ public static string GetAotArguments (Application app, string filename, Abi abi, args.Append ("llvmonly,"); else if (interp) args.Append ("interp,"); + else if (interp_mixed) + args.Append ("interp,full,"); else args.Append ("full,"); @@ -641,7 +644,7 @@ public static string GenerateMain (Application app, IEnumerable assemb sw.WriteLine ("xamarin_profiler_symbol_def xamarin_profiler_symbol = NULL;"); } - if (app.UseInterpreter) { + if (app.UseInterpreter || app.UseInterpreterMixed) { sw.WriteLine ("extern \"C\" { void mono_ee_interp_init (const char *); }"); sw.WriteLine ("extern \"C\" { void mono_icall_table_init (void); }"); sw.WriteLine ("extern \"C\" { void mono_marshal_ilgen_init (void); }"); @@ -657,7 +660,7 @@ public static string GenerateMain (Application app, IEnumerable assemb if (app.EnableLLVMOnlyBitCode) sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY);"); - else if (app.UseInterpreter) { + else if (app.UseInterpreter || app.UseInterpreterMixed) { sw.WriteLine ("\tmono_icall_table_init ();"); sw.WriteLine ("\tmono_marshal_ilgen_init ();"); sw.WriteLine ("\tmono_method_builder_ilgen_init ();"); @@ -866,7 +869,7 @@ public static bool CanWeSymlinkTheApplication (Application app) if (app.EnableSGenConc) return false; - if (app.UseInterpreter) + if (app.UseInterpreter || app.UseInterpreterMixed) return false; if (app.Registrar == RegistrarMode.Static) @@ -1248,6 +1251,7 @@ static Application ParseArguments (string [] args, out Action a) } }, { "interpreter", "Enable the *experimental* interpreter.", v => { app.UseInterpreter = true; }}, + { "interp-mixed", "Enable the *experimental* interpreter mixed with AOT mode.", v => { app.UseInterpreterMixed = true; }}, { "http-message-handler=", "Specify the default HTTP message handler for HttpClient", v => { http_message_handler = v; }}, { "output-format=", "Specify the output format for some commands. Possible values: Default, XML", v => { From d3704d42fa8a81408c0bf6dc26e9e6ec6eaeb019 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 6 Sep 2018 16:37:13 +0200 Subject: [PATCH 2/7] [mtouch] Add support to --interpreter to list the assemblies to (not) interpret. --- .../Tasks/MTouchTaskBase.cs | 14 ++++--- .../Xamarin.iOS.Common.props | 2 +- .../Xamarin.iOS.Common.targets | 2 +- tests/common/BundlerTool.cs | 8 +++- tests/mtouch/MTouch.cs | 19 +++++++++ tests/xharness/Jenkins.cs | 6 +-- tools/common/Application.cs | 40 ++++++++++++++++++- tools/mtouch/Application.cs | 18 +++++++-- tools/mtouch/Assembly.cs | 22 ++++------ tools/mtouch/Target.cs | 28 +++++++++++-- tools/mtouch/mtouch.cs | 22 ++++++---- 11 files changed, 139 insertions(+), 42 deletions(-) diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs index 1cd724b8ee82..bb0ddbeccd5a 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs +++ b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs @@ -110,7 +110,7 @@ public GccOptions () public bool UseInterpreter { get; set; } [Required] - public bool UseInterpreterMixed { get; set; } + public string Interpreter { get; set; } [Required] public bool LinkerDumpDependencies { get; set; } @@ -408,11 +408,13 @@ protected override string GenerateCommandLineCommands () if (EnableSGenConc) args.AddLine ("--sgen-conc"); - if (UseInterpreter) - args.Add ("--interpreter"); - - if (UseInterpreterMixed) - args.Add ("--interp-mixed"); + if (UseInterpreter) { + if (string.IsNullOrEmpty (Interpreter)) { + args.Add ("--interpreter"); + } else { + args.Add ($"--interpreter={Interpreter}"); + } + } switch (LinkMode.ToLowerInvariant ()) { case "sdkonly": args.AddLine ("--linksdkonly"); break; diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props index 91bd8e3e05bf..afec9e37707b 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props +++ b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props @@ -52,7 +52,7 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved. $(MSBuildProjectDirectory) False False - False + all 2 true diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets index 8aa48a931e2c..cd109b537cfd 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets +++ b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets @@ -832,7 +832,7 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved. EnableBitcode="$(MtouchEnableBitcode)" EnableSGenConc="$(MtouchEnableSGenConc)" UseInterpreter="$(MtouchUseInterpreter)" - UseInterpreterMixed="$(MtouchUseInterpreterMixed)" + Interpreter="$(MtouchInterpreter)" AppExtensionReferences="@(_ResolvedAppExtensionReferences)" ArchiveSymbols="$(MonoSymbolArchive)" Verbosity="$(MtouchVerbosity)" diff --git a/tests/common/BundlerTool.cs b/tests/common/BundlerTool.cs index 498c95d6076e..65fba9979882 100644 --- a/tests/common/BundlerTool.cs +++ b/tests/common/BundlerTool.cs @@ -74,6 +74,7 @@ abstract class BundlerTool : Tool public int Verbosity; public int [] WarnAsError; // null array: nothing passed to mtouch/mmp. empty array: pass --warnaserror (which means makes all warnings errors). public string [] XmlDefinitions; + public string Interpreter; // These are a bit smarter public bool NoPlatformAssemblyReference; @@ -291,7 +292,12 @@ protected virtual void BuildArguments (StringBuilder sb) sb.Append (" --xml:").Append (StringUtils.Quote (xd)); } - + if (Interpreter != null) { + if (Interpreter.Length == 0) + sb.Append (" --interpreter"); + else + sb.Append (" --interpreter=").Append (Interpreter); + } } public string CreateTemporaryDirectory () diff --git a/tests/mtouch/MTouch.cs b/tests/mtouch/MTouch.cs index 34cca5475041..4644e1001ee1 100644 --- a/tests/mtouch/MTouch.cs +++ b/tests/mtouch/MTouch.cs @@ -1780,6 +1780,25 @@ public class B } } + [Test] + public void MT0138 () + { + using (var mtouch = new MTouchTool ()) { + var tmpdir = mtouch.CreateTemporaryDirectory (); + mtouch.CreateTemporaryCacheDirectory (); + + mtouch.CreateTemporaryApp (); + mtouch.WarnAsError = new int [] { 138 }; // This is just to make mtouch bail out early instead of spending time building the app when that's not what we're interested in. + mtouch.Interpreter = "all,-all,foo,-bar,mscorlib.dll,mscorlib"; + mtouch.AssertExecuteFailure (MTouchAction.BuildSim, "build"); + mtouch.AssertError (138, "Cannot find the assembly 'foo', passed as an argument to --interpreter."); + mtouch.AssertError (138, "Cannot find the assembly 'bar', passed as an argument to --interpreter."); + mtouch.AssertError (138, "Cannot find the assembly 'mscorlib.dll', passed as an argument to --interpreter."); + // just the name, without the extension, is the right way. + mtouch.AssertErrorCount (3); + } + } + [Test] [TestCase ("all")] [TestCase ("-all")] diff --git a/tests/xharness/Jenkins.cs b/tests/xharness/Jenkins.cs index efae10231260..5cc986274557 100644 --- a/tests/xharness/Jenkins.cs +++ b/tests/xharness/Jenkins.cs @@ -182,15 +182,15 @@ IEnumerable GetTestData (RunTestTask test) yield return new TestData { Variation = "Release (all optimizations)", MTouchExtraArgs = "--registrar:static --optimize:all", Debug = false, Profiling = false, Defines = "OPTIMIZEALL" }; yield return new TestData { Variation = "Debug (all optimizations)", MTouchExtraArgs = "--registrar:static --optimize:all", Debug = true, Profiling = false, Defines = "OPTIMIZEALL" }; yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, Ignored = true, }; - yield return new TestData { Variation = "Debug (interp-mixed)", MTouchExtraArgs = "--interp-mixed", Debug = true, Profiling = false, Ignored = true, }; + yield return new TestData { Variation = "Debug (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = true, Profiling = false, Ignored = true, }; break; case "mscorlib": yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, Ignored = true, Undefines = "FULL_AOT_RUNTIME" }; - yield return new TestData { Variation = "Debug (interp-mixed)", MTouchExtraArgs = "--interp-mixed", Debug = true, Profiling = false, Ignored = true, Undefines = "FULL_AOT_RUNTIME" }; + yield return new TestData { Variation = "Debug (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = true, Profiling = false, Ignored = true, Undefines = "FULL_AOT_RUNTIME" }; break; case "mini": yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, Undefines = "FULL_AOT_RUNTIME" }; - yield return new TestData { Variation = "Debug (interp-mixed)", MTouchExtraArgs = "--interp-mixed", Debug = true, Profiling = false, Undefines = "FULL_AOT_RUNTIME" }; + yield return new TestData { Variation = "Debug (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = true, Profiling = false, Undefines = "FULL_AOT_RUNTIME" }; break; } break; diff --git a/tools/common/Application.cs b/tools/common/Application.cs index 6611a7048ec6..0ba69a51cccd 100644 --- a/tools/common/Application.cs +++ b/tools/common/Application.cs @@ -64,7 +64,7 @@ public partial class Application public bool? EnableCoopGC; public bool EnableSGenConc; public bool UseInterpreter; - public bool UseInterpreterMixed; + public List InterpretedAssemblies = new List (); public MarshalObjectiveCExceptionMode MarshalObjectiveCExceptions; public MarshalManagedExceptionMode MarshalManagedExceptions; @@ -94,6 +94,44 @@ public bool DynamicRegistrationSupported { } } + public bool IsInterpreted (string assembly) + { + // IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both. + if (!UseInterpreter) + return false; + + // Go through the list of assemblies to interpret in reverse order, + // so that the last option passed to mtouch takes precedence. + for (int i = InterpretedAssemblies.Count - 1; i >= 0; i--) { + var opt = InterpretedAssemblies [i]; + if (opt == "all") + return true; + else if (opt == "-all") + return false; + else if (opt == assembly) + return true; + else if (opt [0] == '-' && opt.Substring (1) == assembly) + return false; + } + + // There's an implicit 'all' at the start of the list. + return true; + } + + public bool IsAOTCompiled (string assembly) + { + if (!UseInterpreter) + return true; + + // IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both: + // - mscorlib will always be processed by the AOT compiler to generate required wrapper functions for the interpreter to work + // - mscorlib might also be fully AOT-compiled (both when the interpreter is enabled and when it's not) + if (assembly == "mscorlib") + return true; + + return !IsInterpreted (assembly); + } + // This is just a name for this app to show in log/error messages, etc. public string Name { get { return Path.GetFileNameWithoutExtension (AppDirectory); } diff --git a/tools/mtouch/Application.cs b/tools/mtouch/Application.cs index c0b10b481e4f..4677771baa86 100644 --- a/tools/mtouch/Application.cs +++ b/tools/mtouch/Application.cs @@ -462,7 +462,7 @@ public bool UseDlsym (string assembly) if (EnableLLVMOnlyBitCode) return false; - if (UseInterpreter || UseInterpreterMixed) + if (IsInterpreted (Assembly.GetIdentity (assembly))) return true; switch (Platform) { @@ -2124,8 +2124,20 @@ public void StripNativeCode () public void BundleAssemblies () { - /* TODO: must be more fine-grained for UseInterpreterMixed case */ - var strip = !UseInterpreter && !UseInterpreterMixed && ManagedStrip && IsDeviceBuild && !EnableDebug && !PackageManagedDebugSymbols; + Assembly.StripAssembly strip = ((path) => + { + if (!ManagedStrip) + return false; + if (!IsDeviceBuild) + return false; + if (EnableDebug) + return false; + if (PackageManagedDebugSymbols) + return false; + if (IsInterpreted (Assembly.GetIdentity (path))) + return false; + return true; + }); var grouped = Targets.SelectMany ((Target t) => t.Assemblies).GroupBy ((Assembly asm) => asm.Identity); foreach (var @group in grouped) { diff --git a/tools/mtouch/Assembly.cs b/tools/mtouch/Assembly.cs index 09d358495f86..ac37322c80c3 100644 --- a/tools/mtouch/Assembly.cs +++ b/tools/mtouch/Assembly.cs @@ -54,16 +54,7 @@ public HashSet DependencyMap { public bool IsAOTCompiled { get { - if (App.UseInterpreter) - /* interpreter only requires a few stubs that are attached - * to mscorlib.dll, other assemblies won't be AOT compiled */ - return FileName == "mscorlib.dll"; - if (App.UseInterpreterMixed) - /* TODO: for now, only (fully) AOT compile mscorlib.dll. We - * need an additional option to drive what assemblies - * should be AOT compiled */ - return FileName == "mscorlib.dll"; - return true; + return App.IsAOTCompiled (Identity); } } @@ -113,15 +104,18 @@ public void ComputeDependencyMap (List exceptions) ComputeDependencies (exceptions); } + public delegate bool StripAssembly (string path); + // returns false if the assembly was not copied (because it was already up-to-date). - public bool CopyAssembly (string source, string target, bool copy_debug_symbols = true, bool strip = false) + public bool CopyAssembly (string source, string target, bool copy_debug_symbols = true, StripAssembly strip = null) { var copied = false; try { - if (!Application.IsUptodate (source, target) && (strip || !Cache.CompareAssemblies (source, target))) { + var strip_assembly = strip != null && strip (source); + if (!Application.IsUptodate (source, target) && (strip_assembly || !Cache.CompareAssemblies (source, target))) { copied = true; - if (strip) { + if (strip_assembly) { Driver.FileDelete (target); Directory.CreateDirectory (Path.GetDirectoryName (target)); MonoTouch.Tuner.Stripper.Process (source, target); @@ -200,7 +194,7 @@ public void CopyConfigToDirectory (string directory) // Aot data is copied separately, because we might want to copy aot data // even if we don't want to copy the assembly (if 32/64-bit assemblies are identical, // only one is copied, but we still want the aotdata for both). - public void CopyToDirectory (string directory, bool reload = true, bool check_case = false, bool only_copy = false, bool copy_debug_symbols = true, bool strip = false) + public void CopyToDirectory (string directory, bool reload = true, bool check_case = false, bool only_copy = false, bool copy_debug_symbols = true, StripAssembly strip = null) { var target = Path.Combine (directory, FileName); diff --git a/tools/mtouch/Target.cs b/tools/mtouch/Target.cs index f9e89de9af0a..fdd067bf1d80 100644 --- a/tools/mtouch/Target.cs +++ b/tools/mtouch/Target.cs @@ -283,6 +283,29 @@ public void Initialize (bool show_warnings) } linker_flags = new CompilerFlags (this); + + // Verify that there are no entries in our list of intepreted assemblies that doesn't match + // any of the assemblies we know about. + if (App.UseInterpreter) { + var exceptions = new List (); + foreach (var entry in App.InterpretedAssemblies) { + var assembly = entry; + if (string.IsNullOrEmpty (assembly)) + continue; + + if (assembly [0] == '-') + assembly = assembly.Substring (1); + + if (assembly == "all") + continue; + + if (Assemblies.ContainsKey (assembly)) + continue; + + exceptions.Add (ErrorHelper.CreateWarning (138, $"Cannot find the assembly '{assembly}', passed as an argument to --interpreter.")); + } + ErrorHelper.ThrowIfErrors (exceptions); + } } // This is to load the symbols for all assemblies, so that we can give better error messages @@ -1134,9 +1157,6 @@ void AOTCompile () } if (App.UseInterpreter) - return; - - if (App.UseInterpreterMixed) /* TODO: not sure? we might have to continue here, depending on * the set of assemblies are AOT'd? */ return; @@ -1489,7 +1509,7 @@ public void NativeLink (BuildTasks build_tasks) } } - if (App.UseInterpreter || App.UseInterpreterMixed) { + if (App.UseInterpreter) { string libinterp = Path.Combine (libdir, "libmono-ee-interp.a"); linker_flags.AddLinkWith (libinterp); string libicalltable = Path.Combine (libdir, "libmono-icall-table.a"); diff --git a/tools/mtouch/mtouch.cs b/tools/mtouch/mtouch.cs index 2edf3a08a4de..ff6629aa5acd 100644 --- a/tools/mtouch/mtouch.cs +++ b/tools/mtouch/mtouch.cs @@ -455,8 +455,8 @@ public static string GetAotArguments (Application app, string filename, Abi abi, bool enable_debug = app.EnableDebug; bool enable_debug_symbols = app.PackageManagedDebugSymbols; bool llvm_only = app.EnableLLVMOnlyBitCode; - bool interp = app.UseInterpreter; - bool interp_mixed = app.UseInterpreterMixed; + bool interp = app.IsInterpreted (Assembly.GetIdentity (filename)); + bool interp_full = !interp && app.UseInterpreter && fname == "mscorlib.dll"; bool is32bit = (abi & Abi.Arch32Mask) > 0; string arch = abi.AsArchString (); @@ -477,7 +477,7 @@ public static string GetAotArguments (Application app, string filename, Abi abi, args.Append ("llvmonly,"); else if (interp) args.Append ("interp,"); - else if (interp_mixed) + else if (interp_full) args.Append ("interp,full,"); else args.Append ("full,"); @@ -644,7 +644,7 @@ public static string GenerateMain (Application app, IEnumerable assemb sw.WriteLine ("xamarin_profiler_symbol_def xamarin_profiler_symbol = NULL;"); } - if (app.UseInterpreter || app.UseInterpreterMixed) { + if (app.UseInterpreter) { sw.WriteLine ("extern \"C\" { void mono_ee_interp_init (const char *); }"); sw.WriteLine ("extern \"C\" { void mono_icall_table_init (void); }"); sw.WriteLine ("extern \"C\" { void mono_marshal_ilgen_init (void); }"); @@ -660,7 +660,7 @@ public static string GenerateMain (Application app, IEnumerable assemb if (app.EnableLLVMOnlyBitCode) sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY);"); - else if (app.UseInterpreter || app.UseInterpreterMixed) { + else if (app.UseInterpreter) { sw.WriteLine ("\tmono_icall_table_init ();"); sw.WriteLine ("\tmono_marshal_ilgen_init ();"); sw.WriteLine ("\tmono_method_builder_ilgen_init ();"); @@ -869,7 +869,7 @@ public static bool CanWeSymlinkTheApplication (Application app) if (app.EnableSGenConc) return false; - if (app.UseInterpreter || app.UseInterpreterMixed) + if (app.UseInterpreter) return false; if (app.Registrar == RegistrarMode.Static) @@ -1250,8 +1250,14 @@ static Application ParseArguments (string [] args, out Action a) app.LLVMOptimizations [asm] = opt; } }, - { "interpreter", "Enable the *experimental* interpreter.", v => { app.UseInterpreter = true; }}, - { "interp-mixed", "Enable the *experimental* interpreter mixed with AOT mode.", v => { app.UseInterpreterMixed = true; }}, + { "interpreter:", "Enable the *experimental* interpreter. Optionally takes a comma-separated list of assemblies to interpret (if prefixed with a minus sign, the assembly will be AOT-compiled instead). 'all' can be used to specify all assemblies. This argument can be specified multiple times.", v => + { + app.UseInterpreter = true; + if (!string.IsNullOrEmpty (v)) { + app.InterpretedAssemblies.AddRange (v.Split (new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries)); + } + } + }, { "http-message-handler=", "Specify the default HTTP message handler for HttpClient", v => { http_message_handler = v; }}, { "output-format=", "Specify the output format for some commands. Possible values: Default, XML", v => { From 6020e9876b424f62d95a4ea13dc9f70b1912f525 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 7 Sep 2018 16:23:19 +0200 Subject: [PATCH 3/7] [msbuild] Simplify interpreter code to use a single variable. --- .../Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs | 12 ++---------- .../Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props | 2 -- .../Xamarin.iOS.Common.targets | 1 - 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs index bb0ddbeccd5a..7215652ad3a2 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs +++ b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs @@ -106,9 +106,6 @@ public GccOptions () [Required] public bool EnableSGenConc { get; set; } - [Required] - public bool UseInterpreter { get; set; } - [Required] public string Interpreter { get; set; } @@ -408,13 +405,8 @@ protected override string GenerateCommandLineCommands () if (EnableSGenConc) args.AddLine ("--sgen-conc"); - if (UseInterpreter) { - if (string.IsNullOrEmpty (Interpreter)) { - args.Add ("--interpreter"); - } else { - args.Add ($"--interpreter={Interpreter}"); - } - } + if (!string.IsNullOrEmpty (Interpreter)) + args.Add ($"--interpreter={Interpreter}"); switch (LinkMode.ToLowerInvariant ()) { case "sdkonly": args.AddLine ("--linksdkonly"); break; diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props index afec9e37707b..a29b7e7a18e5 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props +++ b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.props @@ -51,8 +51,6 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved. False $(MSBuildProjectDirectory) False - False - all 2 true diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets index cd109b537cfd..ff54f2301f14 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets +++ b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets @@ -831,7 +831,6 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved. UseThumb="$(MtouchUseThumb)" EnableBitcode="$(MtouchEnableBitcode)" EnableSGenConc="$(MtouchEnableSGenConc)" - UseInterpreter="$(MtouchUseInterpreter)" Interpreter="$(MtouchInterpreter)" AppExtensionReferences="@(_ResolvedAppExtensionReferences)" ArchiveSymbols="$(MonoSymbolArchive)" From 26fb75ca70110cdf6788fad27530d544d05bbf23 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 7 Sep 2018 16:23:39 +0200 Subject: [PATCH 4/7] Fix whitespace. --- tools/mtouch/mtouch.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/mtouch/mtouch.cs b/tools/mtouch/mtouch.cs index ff6629aa5acd..c378897f23dc 100644 --- a/tools/mtouch/mtouch.cs +++ b/tools/mtouch/mtouch.cs @@ -1254,7 +1254,7 @@ static Application ParseArguments (string [] args, out Action a) { app.UseInterpreter = true; if (!string.IsNullOrEmpty (v)) { - app.InterpretedAssemblies.AddRange (v.Split (new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries)); + app.InterpretedAssemblies.AddRange (v.Split (new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries)); } } }, From 8e52101b86b27469e43b47c1902ebcc6fe0603fe Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 7 Sep 2018 16:23:54 +0200 Subject: [PATCH 5/7] [mtouch] Move mtouch-specific code to mtouch-specific file. --- tools/common/Application.cs | 40 ------------------------------------- tools/mtouch/Application.cs | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/tools/common/Application.cs b/tools/common/Application.cs index 0ba69a51cccd..b111651dbf80 100644 --- a/tools/common/Application.cs +++ b/tools/common/Application.cs @@ -63,8 +63,6 @@ public partial class Application public bool? EnableCoopGC; public bool EnableSGenConc; - public bool UseInterpreter; - public List InterpretedAssemblies = new List (); public MarshalObjectiveCExceptionMode MarshalObjectiveCExceptions; public MarshalManagedExceptionMode MarshalManagedExceptions; @@ -94,44 +92,6 @@ public bool DynamicRegistrationSupported { } } - public bool IsInterpreted (string assembly) - { - // IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both. - if (!UseInterpreter) - return false; - - // Go through the list of assemblies to interpret in reverse order, - // so that the last option passed to mtouch takes precedence. - for (int i = InterpretedAssemblies.Count - 1; i >= 0; i--) { - var opt = InterpretedAssemblies [i]; - if (opt == "all") - return true; - else if (opt == "-all") - return false; - else if (opt == assembly) - return true; - else if (opt [0] == '-' && opt.Substring (1) == assembly) - return false; - } - - // There's an implicit 'all' at the start of the list. - return true; - } - - public bool IsAOTCompiled (string assembly) - { - if (!UseInterpreter) - return true; - - // IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both: - // - mscorlib will always be processed by the AOT compiler to generate required wrapper functions for the interpreter to work - // - mscorlib might also be fully AOT-compiled (both when the interpreter is enabled and when it's not) - if (assembly == "mscorlib") - return true; - - return !IsInterpreted (assembly); - } - // This is just a name for this app to show in log/error messages, etc. public string Name { get { return Path.GetFileNameWithoutExtension (AppDirectory); } diff --git a/tools/mtouch/Application.cs b/tools/mtouch/Application.cs index 4677771baa86..9d8d6d336441 100644 --- a/tools/mtouch/Application.cs +++ b/tools/mtouch/Application.cs @@ -116,6 +116,8 @@ public bool EnableMSym { public string AotOtherArguments = string.Empty; public bool? LLVMAsmWriter; public Dictionary LLVMOptimizations = new Dictionary (); + public bool UseInterpreter; + public List InterpretedAssemblies = new List (); public Dictionary EnvironmentVariables = new Dictionary (); @@ -129,6 +131,44 @@ public bool EnableMSym { public bool? BuildDSym; + public bool IsInterpreted (string assembly) + { + // IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both. + if (!UseInterpreter) + return false; + + // Go through the list of assemblies to interpret in reverse order, + // so that the last option passed to mtouch takes precedence. + for (int i = InterpretedAssemblies.Count - 1; i >= 0; i--) { + var opt = InterpretedAssemblies [i]; + if (opt == "all") + return true; + else if (opt == "-all") + return false; + else if (opt == assembly) + return true; + else if (opt [0] == '-' && opt.Substring (1) == assembly) + return false; + } + + // There's an implicit 'all' at the start of the list. + return true; + } + + public bool IsAOTCompiled (string assembly) + { + if (!UseInterpreter) + return true; + + // IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both: + // - mscorlib will always be processed by the AOT compiler to generate required wrapper functions for the interpreter to work + // - mscorlib might also be fully AOT-compiled (both when the interpreter is enabled and when it's not) + if (assembly == "mscorlib") + return true; + + return !IsInterpreted (assembly); + } + // If we're targetting a 32 bit arch. bool? is32bits; public bool Is32Build { From 7629ec6a28ffe6073351a1ce05f6a8c5bafa93ec Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 10 Sep 2018 07:35:50 +0200 Subject: [PATCH 6/7] [msbuild] An empty string is a valid value for 'Interpreter', so make it a non-required property. --- msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs index 7215652ad3a2..7d58d6e37591 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs +++ b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/MTouchTaskBase.cs @@ -106,7 +106,6 @@ public GccOptions () [Required] public bool EnableSGenConc { get; set; } - [Required] public string Interpreter { get; set; } [Required] From f7e11cf2d6f4b158bf215b0ea0376da8c088c200 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 11 Sep 2018 07:39:01 +0200 Subject: [PATCH 7/7] [mtouch] Add sanity check for aot-compiling interpreted assemblies. --- tools/mtouch/mtouch.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/mtouch/mtouch.cs b/tools/mtouch/mtouch.cs index c378897f23dc..ed27746d98e8 100644 --- a/tools/mtouch/mtouch.cs +++ b/tools/mtouch/mtouch.cs @@ -475,11 +475,15 @@ public static string GetAotArguments (Application app, string filename, Abi abi, args.Append (app.AotArguments); if (llvm_only) args.Append ("llvmonly,"); - else if (interp) + else if (interp) { + if (fname != "mscorlib.dll") + throw ErrorHelper.CreateError (99, $"Internal error: can only enable the interpreter for mscorlib.dll when AOT-compiling assemblies (tried to interpret {fname}). Please file an issue at https://github.com/xamarin/xamarin-macios/issues/new."); args.Append ("interp,"); - else if (interp_full) + } else if (interp_full) { + if (fname != "mscorlib.dll") + throw ErrorHelper.CreateError (99, $"Internal error: can only enable the interpreter for mscorlib.dll when AOT-compiling assemblies (tried to interpret {fname}). Please file an issue at https://github.com/xamarin/xamarin-macios/issues/new."); args.Append ("interp,full,"); - else + } else args.Append ("full,"); var aname = Path.GetFileNameWithoutExtension (fname);