From dbd67c0b0005af90e8cb354b5eccbb96e2487574 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 12 Mar 2021 07:25:12 -0500 Subject: [PATCH 1/2] [wasm] Disable the linkonce linking of wrappers for now, the aot metadata about wrappers is not dedup-ed, so a separate dedup pass still saves more space. --- src/mono/mono/mini/aot-runtime.c | 3 +++ src/mono/mono/mini/llvm-runtime.cpp | 12 ++++++++++++ src/mono/mono/mini/mini-llvm.c | 3 +++ 3 files changed, 18 insertions(+) diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 7bbeb4098de89..816d5394eeb8e 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -4337,9 +4337,12 @@ mono_aot_can_dedup (MonoMethod *method) info->subtype == WRAPPER_SUBTYPE_INTERP_LMF || info->subtype == WRAPPER_SUBTYPE_AOT_INIT) return FALSE; +#if 0 + // See is_linkonce_method () in mini-llvm.c if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG || info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG) /* Handled using linkonce */ return FALSE; +#endif return TRUE; } default: diff --git a/src/mono/mono/mini/llvm-runtime.cpp b/src/mono/mono/mini/llvm-runtime.cpp index 9982cccfb0f98..a621ae80b26d0 100644 --- a/src/mono/mono/mini/llvm-runtime.cpp +++ b/src/mono/mono/mini/llvm-runtime.cpp @@ -3,6 +3,10 @@ #include +#ifdef HOST_WASM +#include +#endif + extern "C" { void @@ -10,6 +14,14 @@ mono_llvm_cpp_throw_exception (void) { gint32 *ex = NULL; +#ifdef HOST_WASM + EM_ASM( + var err = new Error(); + console.log ("Throw stacktrace: \n"); + console.log (err.stack); + ); +#endif + /* The generated code catches an int32* */ throw ex; } diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 506031a2b1709..19b9077dff525 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -9521,11 +9521,14 @@ is_linkonce_method (MonoMethod *method) * FIXME: Fails System.Core tests * -> amodule->sorted_methods contains duplicates, screwing up jit tables. */ + // FIXME: This works, but the aot data for the methods is still kept, so size still increases +#if 0 if (method->wrapper_type == MONO_WRAPPER_OTHER) { WrapperInfo *info = mono_marshal_get_wrapper_info (method); if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG || info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG) return TRUE; } +#endif #endif return FALSE; } From 1a34f2fc947d4a5371987ee303c6f52f147f9a6f Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 12 Mar 2021 07:32:55 -0500 Subject: [PATCH 2/2] [wasm] Add dedup support to the build to avoid generating generic instances etc. multiple times. This works as follows: * Controlled by a new public 'WasmDedup' property, defaults to true. * All assemblies are AOT compiled with the 'dedup-skip' option, which causes the AOT compiler to avoid generating generic instances, certain wrappers etc. * A new internal assembly called aot-instances.dll is added to the build. * When aot-instances.dll is AOTed, all the other assemblies are AOTed together, but only the generic instances/wrappers are emitted into its AOT image. --- src/mono/wasm/build/WasmApp.targets | 26 ++++++++++- src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 48 +++++++++++++++++++- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 34732b71be2dc..964b162645555 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -24,6 +24,7 @@ - $(WasmDebugLevel) - $(WasmNativeDebugSymbols) - Build with native debug symbols, useful only with `$(RunAOTCompilation)`, or `$(WasmBuildNative)` Defaults to true. + - $(WasmDedup) - Whenever to dedup generic instances when using AOT. Defaults to true. - $(WasmProfilers) - Profilers to use - $(AOTMode) - Defaults to `AotInterp` @@ -64,6 +65,7 @@ false + $(RunAOTCompilation) @@ -106,6 +108,27 @@ Text="Builing in AOTMode=LLVMonly, but found some assemblies marked as _InternalForceInterpret: @(_AOT_InternalForceInterpretAssemblies)" /> + + + + <_WasmDedupAssembly>$(_WasmIntermediateOutputPath)\aot-instances.dll + + + + + <_AotInputAssemblies Include="$(_WasmDedupAssembly)"> + @(MonoAOTCompilerDefaultAotArguments, ';') + @(MonoAOTCompilerDefaultProcessArguments, ';') + + + @@ -407,7 +431,7 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_ - diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index d7a7ab6967489..fc5f9b70c43cd 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -121,6 +121,11 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task /// public string? MsymPath { get; set; } + /// + /// The assembly whose AOT image will contained dedup-ed generic instances + /// + public string? DedupAssembly { get; set; } + [Output] public string[]? FileWrites { get; private set; } @@ -242,6 +247,7 @@ private bool PrecompileLibrary(ITaskItem assemblyItem, string? monoPaths) var aotAssembly = new TaskItem(assembly); var aotArgs = new List(); var processArgs = new List(); + bool isDedup = assembly == DedupAssembly; var a = assemblyItem.GetMetadata("AotArguments"); if (a != null) @@ -274,6 +280,15 @@ private bool PrecompileLibrary(ITaskItem assemblyItem, string? monoPaths) string assemblyFilename = Path.GetFileName(assembly); + if (isDedup) + { + aotArgs.Add($"dedup-include={assemblyFilename}"); + } + else if (!string.IsNullOrEmpty (DedupAssembly)) + { + aotArgs.Add("dedup-skip"); + } + // compute output mode and file names if (parsedAotMode == MonoAotMode.LLVMOnly || parsedAotMode == MonoAotMode.AotInterp) { @@ -350,14 +365,43 @@ private bool PrecompileLibrary(ITaskItem assemblyItem, string? monoPaths) // values, which wont work. processArgs.Add($"\"--aot={string.Join(",", aotArgs)}\""); - processArgs.Add($"\"{assemblyFilename}\""); + string paths = ""; + if (isDedup) + { + StringBuilder sb = new StringBuilder(); + HashSet allPaths = new HashSet(); + foreach (var aItem in Assemblies) + { + string filename = aItem.ItemSpec; + processArgs.Add(filename); + string dir = Path.GetDirectoryName(filename)!; + if (!allPaths.Contains(dir)) + { + allPaths.Add(dir); + if (sb.Length > 0) + sb.Append(Path.PathSeparator); + sb.Append(dir); + } + } + if (sb.Length > 0) + sb.Append(Path.PathSeparator); + sb.Append(monoPaths); + paths = sb.ToString(); + } + else + { + paths = $"{assemblyDir}{Path.PathSeparator}{monoPaths}"; + processArgs.Add(assemblyFilename); + } var envVariables = new Dictionary { - {"MONO_PATH", $"{assemblyDir}{Path.PathSeparator}{monoPaths}"}, + {"MONO_PATH", paths}, {"MONO_ENV_OPTIONS", string.Empty} // we do not want options to be provided out of band to the cross compilers }; + Utils.LogInfo ($"MONO_PATH={paths}"); + try { // run the AOT compiler