Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WASM] Add ILStrip task to wasm app build process #88926

Merged
merged 21 commits into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/workflow/building/mono/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ For `build.sh`

`/p:DisableCrossgen=true` - Skips building the installer if you don't need it (builds faster)

`-p:KeepNativeSymbols=true` - Keep the symbols in the binary instead of stripping them out to a separate file. This helps with debugging Mono with lldb.
`/p:KeepNativeSymbols=true` - Keep the symbols in the binary instead of stripping them out to a separate file. This helps with debugging Mono with lldb.

The build has a number of options that you can learn about using build -?.

Expand Down
7 changes: 7 additions & 0 deletions src/libraries/tests.proj
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,13 @@
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.WebSockets.Client\tests\System.Net.WebSockets.Client.Tests.csproj" />
</ItemGroup>

<!-- Test WASM with WASMStripIL enabled -->
<ItemGroup Condition="'$(TargetOS)' == 'browser' and '$(RunAOTCompilation)' == 'true'">
<SmokeTestProject Include="$(RepoRoot)\src\tests\FunctionalTests\WebAssembly\Browser\StartupHook\WebAssembly.Browser.StartupHook.Test.csproj"
AdditionalProperties="%(AdditionalProperties);WASMStripIL=true;TestProjectName=WebAssembly_Browser_StartupHook_Test_ILStripped"
BuildInParallel="false" />
</ItemGroup>

<!-- Aggressive Trimming related failures -->
<ItemGroup Condition="('$(TargetOS)' != 'browser' and '$(RunAOTCompilation)' == 'true' and '$(MonoForceInterpreter)' != 'true') or ('$(TargetOS)' == 'browser' and '$(BuildAOTTestsOnHelix)' == 'true' and '$(RunDisabledWasmTests)' != 'true')">
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -9832,7 +9832,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
mono_atomic_inc_i32 (&acfg->stats.ccount);

if (acfg->aot_opts.compiled_methods_outfile && acfg->compiled_methods_outfile != NULL) {
if (!mono_method_is_generic_impl (method) && method->token != 0) {
if (!mono_method_is_generic_impl (method) && method->token != 0 && !cfg->deopt && !cfg->interp_entry_only && mini_get_interp_callbacks ()->jit_call_can_be_supported (method, mono_method_signature_internal (method))) {
fanyang-mono marked this conversation as resolved.
Show resolved Hide resolved
fprintf (acfg->compiled_methods_outfile, "%x\n", method->token);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/ee.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ typedef gpointer MonoInterpFrameHandle;
MONO_EE_CALLBACK (void, entry_llvmonly, (gpointer res, gpointer *args, gpointer imethod)) \
MONO_EE_CALLBACK (gpointer, get_interp_method, (MonoMethod *method)) \
MONO_EE_CALLBACK (MonoJitInfo*, compile_interp_method, (MonoMethod *method, MonoError *error)) \
MONO_EE_CALLBACK (gboolean, jit_call_can_be_supported, (MonoMethod *method, MonoMethodSignature *sig)) \

typedef struct _MonoEECallbacks {

Expand Down
6 changes: 6 additions & 0 deletions src/mono/mono/mini/interp-stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,12 @@ stub_compile_interp_method (MonoMethod *method, MonoError *error)
return NULL;
}

static gboolean
stub_jit_call_can_be_supported (MonoMethod *method, MonoMethodSignature *sig)
{
return TRUE;
}

#undef MONO_EE_CALLBACK
#define MONO_EE_CALLBACK(ret, name, sig) stub_ ## name,

Expand Down
3 changes: 3 additions & 0 deletions src/mono/mono/mini/interp/interp-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@ mono_mint_type (MonoType *type);
int
mono_interp_type_size (MonoType *type, int mt, int *align_p);

gboolean
interp_jit_call_can_be_supported (MonoMethod *method, MonoMethodSignature *sig);

#if HOST_BROWSER

gboolean
Expand Down
59 changes: 58 additions & 1 deletion src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -4055,7 +4055,39 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
}
ip += 5;

goto call;
InterpMethodCodeType code_type = cmethod->code_type;

g_assert (code_type == IMETHOD_CODE_UNKNOWN ||
code_type == IMETHOD_CODE_INTERP ||
code_type == IMETHOD_CODE_COMPILED);

if (G_UNLIKELY (code_type == IMETHOD_CODE_UNKNOWN)) {
// FIXME push/pop LMF
MonoMethodSignature *sig = mono_method_signature_internal (cmethod->method);
if (mono_interp_jit_call_supported (cmethod->method, sig))
code_type = IMETHOD_CODE_COMPILED;
else
code_type = IMETHOD_CODE_INTERP;
cmethod->code_type = code_type;
}

if (code_type == IMETHOD_CODE_INTERP) {

goto call;

} else if (code_type == IMETHOD_CODE_COMPILED) {
frame->state.ip = ip;
error_init_reuse (error);
do_jit_call (context, (stackval*)(locals + return_offset), (stackval*)(locals + call_args_offset), frame, cmethod, error);
if (!is_ok (error)) {
MonoException *call_ex = interp_error_convert_to_exception (frame, error, ip);
THROW_EX (call_ex, ip);
}

CHECK_RESUME_STATE (context);
}

MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_CALLI) {
gboolean need_unbox;
Expand Down Expand Up @@ -8569,6 +8601,31 @@ interp_sufficient_stack (gsize size)
return (context->stack_pointer + size) < (context->stack_start + INTERP_STACK_SIZE);
}

gboolean
interp_jit_call_can_be_supported (MonoMethod *method, MonoMethodSignature *sig)
{
if (sig->param_count > 10)
return FALSE;
if (sig->pinvoke)
return FALSE;
if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
return FALSE;
if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
return FALSE;
if (!mono_llvm_only && method->is_inflated)
fanyang-mono marked this conversation as resolved.
Show resolved Hide resolved
return FALSE;
if (method->string_ctor)
return FALSE;
if (method->wrapper_type != MONO_WRAPPER_NONE)
return FALSE;

if (method->flags & METHOD_ATTRIBUTE_REQSECOBJ)
/* Used to mark methods containing StackCrawlMark locals */
return FALSE;

return TRUE;
}

static void
interp_cleanup (void)
{
Expand Down
22 changes: 5 additions & 17 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -1213,23 +1213,7 @@ mono_interp_jit_call_supported (MonoMethod *method, MonoMethodSignature *sig)
{
GSList *l;

if (sig->param_count > 10)
return FALSE;
if (sig->pinvoke)
return FALSE;
if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
return FALSE;
if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
return FALSE;
if (!mono_llvm_only && method->is_inflated)
return FALSE;
if (method->string_ctor)
return FALSE;
if (method->wrapper_type != MONO_WRAPPER_NONE)
return FALSE;

if (method->flags & METHOD_ATTRIBUTE_REQSECOBJ)
/* Used to mark methods containing StackCrawlMark locals */
if (!interp_jit_call_can_be_supported (method, sig))
return FALSE;

if (mono_aot_only && m_class_get_image (method->klass)->aot_module && !(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
Expand Down Expand Up @@ -2982,6 +2966,10 @@ interp_inline_method (TransformData *td, MonoMethod *target_method, MonoMethodHe
int nargs = csignature->param_count + !!csignature->hasthis;
InterpInst *prev_last_ins;

if (header->code_size == 0)
/* IL stripped */
return FALSE;

lambdageek marked this conversation as resolved.
Show resolved Hide resolved
if (csignature->is_inflated)
generic_context = mono_method_get_context (target_method);
else {
Expand Down
1 change: 1 addition & 0 deletions src/mono/wasm/build/WasmApp.InTree.targets
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project>
<!-- This depends on the root Directory.Build.targets imported this file -->
<UsingTask TaskName="MonoAOTCompiler" AssemblyFile="$(MonoAOTCompilerTasksAssemblyPath)" />
<UsingTask TaskName="ILStrip" AssemblyFile="$(MonoTargetsTasksAssemblyPath)" />
fanyang-mono marked this conversation as resolved.
Show resolved Hide resolved
fanyang-mono marked this conversation as resolved.
Show resolved Hide resolved
<UsingTask TaskName="RuntimeConfigParserTask" AssemblyFile="$(MonoTargetsTasksAssemblyPath)" />

<!-- TODO: this breaks runtime tests on Helix due to the file not being there for some reason. Once this is fixed we can remove the UpdateRuntimePack target here -->
Expand Down
13 changes: 13 additions & 0 deletions src/mono/wasm/build/WasmApp.Native.targets
Original file line number Diff line number Diff line change
Expand Up @@ -674,12 +674,25 @@
CacheFilePath="$(_AOTCompilerCacheFile)"
LLVMDebug="dwarfdebug"
LLVMPath="$(EmscriptenUpstreamBinPath)"
CollectCompiledMethods="$(WASMStripIL)"
fanyang-mono marked this conversation as resolved.
Show resolved Hide resolved
CompiledMethodsOutputDirectory="$(_WasmIntermediateOutputPath)tokens"
IntermediateOutputPath="$(_WasmIntermediateOutputPath)"
AotProfilePath="@(AotProfilePath)">

<Output TaskParameter="CompiledAssemblies" ItemName="_WasmAssembliesInternal" />
<Output TaskParameter="FileWrites" ItemName="FileWrites" />
</MonoAOTCompiler>
<ILStrip
Condition=" '$(WASMStripIL)' == 'true' "
TrimIndividualMethods="true"
fanyang-mono marked this conversation as resolved.
Show resolved Hide resolved
Assemblies="@(_WasmAssembliesInternal)">
<Output TaskParameter="TrimmedAssemblies" ItemName="_ILStripTrimmedAssemblies" />
</ILStrip>
<Move
Condition=" '$(WASMStripIL)' == 'true' "
SourceFiles="@(_ILStripTrimmedAssemblies->'%(TrimmedAssemblyFileName)')"
DestinationFiles="@(_ILStripTrimmedAssemblies)"
/>

<ItemGroup>
<_BitcodeFile Include="%(_WasmAssembliesInternal.LlvmBitcodeFile)" />
Expand Down
4 changes: 4 additions & 0 deletions src/mono/wasm/build/WasmApp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
- AppBundle directly contains user files
- AppBundle/_framework contains generated files (dlls, runtime scripts, icu)
- AppBundle/_content contains web files from nuget packages (css, js, etc)
- $(WASMStripIL) - Set to true to enable trimming away AOT compiled methods body (IL code)
fanyang-mono marked this conversation as resolved.
Show resolved Hide resolved
fanyang-mono marked this conversation as resolved.
Show resolved Hide resolved

Public items:
- @(WasmExtraFilesToDeploy) - Files to copy to $(WasmAppDir).
Expand Down Expand Up @@ -144,6 +145,9 @@
<!-- by default, package assemblies as webcil -->
<WasmEnableWebcil Condition="'$(WasmEnableWebcil)' == ''">true</WasmEnableWebcil>

<!-- by default, method body IL code trimming is disabled -->
<WASMStripIL Condition="'$(WASMStripIL)' == ''">false</WASMStripIL>

<WasmRuntimeAssetsLocation Condition="'$(WasmRuntimeAssetsLocation)' == ''">_framework</WasmRuntimeAssetsLocation>
</PropertyGroup>

Expand Down
12 changes: 11 additions & 1 deletion src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ private bool StripAssembly(ITaskItem assemblyItem)

private bool TrimMethods(ITaskItem assemblyItem)
{
string assemblyFilePathArg = assemblyItem.ItemSpec;
string methodTokenFile = assemblyItem.GetMetadata("MethodTokenFile");
if (string.IsNullOrEmpty(methodTokenFile))
{
Expand Down Expand Up @@ -165,7 +166,7 @@ private bool TrimMethods(ITaskItem assemblyItem)

if (isTrimmed)
{
AddItemToTrimmedList(assemblyFilePath, trimmedAssemblyFilePath);
AddItemToTrimmedList(assemblyFilePathArg, trimmedAssemblyFilePath);
}

return true;
Expand Down Expand Up @@ -252,6 +253,8 @@ private void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFile
int methodSize = ComputeMethodSize(peReader, rva);
int actualLoc = ComputeMethodHash(peReader, rva);
int headerSize = ComputeMethodHeaderSize(memStream, actualLoc);
if (headerSize == 1) //Set code size to zero for TinyFormat
SetCodeSizeToZeroForTiny(ref memStream, actualLoc);
ZeroOutMethodBody(ref memStream, methodSize, actualLoc, headerSize);
}
else if (count < 0)
Expand Down Expand Up @@ -282,6 +285,13 @@ private static int ComputeMethodHeaderSize(MemoryStream memStream, int actualLoc
return (headerFlag == 2 ? 1 : 4);
}

private static void SetCodeSizeToZeroForTiny(ref MemoryStream memStream, int actualLoc)
{
memStream.Position = actualLoc;
byte[] header = {0b10};
memStream.Write(header, 0, 1);
}

private static void ZeroOutMethodBody(ref MemoryStream memStream, int methodSize, int actualLoc, int headerSize)
{
memStream.Position = actualLoc + headerSize;
Expand Down