Skip to content

Commit 867e185

Browse files
fanyang-monovargaz
andauthored
[WASM] Add ILStrip task to wasm app build process (#88926)
* Add ILStrip task to wasm app build process * Make it work for wasm app building workflow * Interp: stop inlining stripped methods. ILStrip: set code size to zero for tiny methods * [mono][aot] Avoid adding some methods to the compiled method file. * Methods which have 'deopt' set can enter the interpreter during EH. * Methods which have 'interp_entry_only' set are AOTed, but the AOT code is only used to enter the interpreter. * Only trim the methods that interpreter is able to call the aot'ed verion of it * Add default value and documentation for WASMStripIL * Move jit_call_can_be_supported to interp.c * Minor format fix * Add a test * For testing * Fix typo * Skip TestUtilities Reference * Address review feedback * Change it to true * Change name to trimming eligible * Remove testing * Address review feedback * Address review feedback from Kate * Add a var for llvm_only --------- Co-authored-by: Zoltan Varga <vargaz@gmail.com>
1 parent 15e8925 commit 867e185

14 files changed

Lines changed: 141 additions & 55 deletions

File tree

docs/workflow/building/mono/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ For `build.sh`
6666

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

69-
`-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.
69+
`/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.
7070

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

src/mono/mono/mini/aot-compiler.c

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ typedef struct MonoAotOptions {
188188
char *llvm_outfile;
189189
char *data_outfile;
190190
char *export_symbols_outfile;
191-
char *compiled_methods_outfile;
191+
char *trimming_eligible_methods_outfile;
192192
GList *profile_files;
193193
GList *mibc_profile_files;
194194
gboolean save_temps;
@@ -420,7 +420,7 @@ typedef struct MonoAotCompile {
420420
FILE *logfile;
421421
FILE *instances_logfile;
422422
FILE *data_outfile;
423-
FILE *compiled_methods_outfile;
423+
FILE *trimming_eligible_methods_outfile;
424424
int datafile_offset;
425425
int gc_name_offset;
426426

@@ -8804,8 +8804,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
88048804
opts->llvm_outfile = g_strdup (arg + strlen ("llvm-outfile="));
88058805
} else if (str_begins_with (arg, "export-symbols-outfile=")) {
88068806
opts->export_symbols_outfile = g_strdup (arg + strlen ("export-symbols-outfile="));
8807-
} else if (str_begins_with (arg, "compiled-methods-outfile=")) {
8808-
opts->compiled_methods_outfile = g_strdup (arg + strlen ("compiled-methods-outfile="));
8807+
} else if (str_begins_with (arg, "trimming-eligible-methods-outfile=")) {
8808+
opts->trimming_eligible_methods_outfile = g_strdup (arg + strlen ("trimming-eligible-methods-outfile="));
88098809
} else if (str_begins_with (arg, "temp-path=")) {
88108810
opts->temp_path = clean_path (g_strdup (arg + strlen ("temp-path=")));
88118811
} else if (str_begins_with (arg, "save-temps")) {
@@ -9864,9 +9864,11 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
98649864

98659865
mono_atomic_inc_i32 (&acfg->stats.ccount);
98669866

9867-
if (acfg->aot_opts.compiled_methods_outfile && acfg->compiled_methods_outfile != NULL) {
9868-
if (!mono_method_is_generic_impl (method) && method->token != 0) {
9869-
fprintf (acfg->compiled_methods_outfile, "%x\n", method->token);
9867+
if (acfg->aot_opts.trimming_eligible_methods_outfile && acfg->trimming_eligible_methods_outfile != NULL) {
9868+
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), acfg->aot_opts.llvm_only)) {
9869+
// The call back to jit_call_can_be_supported is necessary for WASM, because it would still interprete some methods sometimes even though they were already AOT'ed.
9870+
// When that happens, interpreter needs to have the capability to call the AOT'ed version of that method, since the method body has already been trimmed.
9871+
fprintf (acfg->trimming_eligible_methods_outfile, "%x\n", method->token);
98709872
}
98719873
}
98729874
}
@@ -14884,13 +14886,13 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1488414886
acfg->logfile = fopen (acfg->aot_opts.logfile, "a+");
1488514887
}
1488614888

14887-
if (acfg->aot_opts.compiled_methods_outfile && acfg->dedup_phase != DEDUP_COLLECT) {
14888-
acfg->compiled_methods_outfile = fopen (acfg->aot_opts.compiled_methods_outfile, "w+");
14889-
if (!acfg->compiled_methods_outfile)
14890-
aot_printerrf (acfg, "Unable to open compiled-methods-outfile specified file %s\n", acfg->aot_opts.compiled_methods_outfile);
14889+
if (acfg->aot_opts.trimming_eligible_methods_outfile && acfg->dedup_phase != DEDUP_COLLECT) {
14890+
acfg->trimming_eligible_methods_outfile = fopen (acfg->aot_opts.trimming_eligible_methods_outfile, "w+");
14891+
if (!acfg->trimming_eligible_methods_outfile)
14892+
aot_printerrf (acfg, "Unable to open trimming-eligible-methods-outfile specified file %s\n", acfg->aot_opts.trimming_eligible_methods_outfile);
1489114893
else {
14892-
fprintf(acfg->compiled_methods_outfile, "%s\n", ass->image->filename);
14893-
fprintf(acfg->compiled_methods_outfile, "%s\n", ass->image->guid);
14894+
fprintf(acfg->trimming_eligible_methods_outfile, "%s\n", ass->image->filename);
14895+
fprintf(acfg->trimming_eligible_methods_outfile, "%s\n", ass->image->guid);
1489414896
}
1489514897
}
1489614898

@@ -15244,8 +15246,8 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1524415246

1524515247
current_acfg = NULL;
1524615248

15247-
if (acfg->compiled_methods_outfile) {
15248-
fclose (acfg->compiled_methods_outfile);
15249+
if (acfg->trimming_eligible_methods_outfile) {
15250+
fclose (acfg->trimming_eligible_methods_outfile);
1524915251
}
1525015252

1525115253
return emit_aot_image (acfg);
@@ -15623,9 +15625,9 @@ mono_aot_assemblies (MonoAssembly **assemblies, int nassemblies, guint32 jit_opt
1562315625
dedup_methods = g_hash_table_new (NULL, NULL);
1562415626
}
1562515627

15626-
if (aot_opts.compiled_methods_outfile) {
15627-
if (g_ensure_directory_exists (aot_opts.compiled_methods_outfile) == FALSE) {
15628-
fprintf (stderr, "AOT : failed to create the directory to save the compiled method names: %s\n", aot_opts.compiled_methods_outfile);
15628+
if (aot_opts.trimming_eligible_methods_outfile) {
15629+
if (g_ensure_directory_exists (aot_opts.trimming_eligible_methods_outfile) == FALSE) {
15630+
fprintf (stderr, "AOT : failed to create the directory to save the trimmable method names: %s\n", aot_opts.trimming_eligible_methods_outfile);
1562915631
exit (1);
1563015632
}
1563115633
}

src/mono/mono/mini/ee.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ typedef gpointer MonoInterpFrameHandle;
6565
MONO_EE_CALLBACK (void, entry_llvmonly, (gpointer res, gpointer *args, gpointer imethod)) \
6666
MONO_EE_CALLBACK (gpointer, get_interp_method, (MonoMethod *method)) \
6767
MONO_EE_CALLBACK (MonoJitInfo*, compile_interp_method, (MonoMethod *method, MonoError *error)) \
68+
MONO_EE_CALLBACK (gboolean, jit_call_can_be_supported, (MonoMethod *method, MonoMethodSignature *sig, gboolean is_llvm_only)) \
6869

6970
typedef struct _MonoEECallbacks {
7071

src/mono/mono/mini/interp-stubs.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,12 @@ stub_compile_interp_method (MonoMethod *method, MonoError *error)
252252
return NULL;
253253
}
254254

255+
static gboolean
256+
stub_jit_call_can_be_supported (MonoMethod *method, MonoMethodSignature *sig, gboolean is_llvm_only)
257+
{
258+
return TRUE;
259+
}
260+
255261
#undef MONO_EE_CALLBACK
256262
#define MONO_EE_CALLBACK(ret, name, sig) stub_ ## name,
257263

src/mono/mono/mini/interp/interp-internals.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,9 @@ mono_mint_type (MonoType *type);
320320
int
321321
mono_interp_type_size (MonoType *type, int mt, int *align_p);
322322

323+
gboolean
324+
interp_jit_call_can_be_supported (MonoMethod *method, MonoMethodSignature *sig, gboolean is_llvm_only);
325+
323326
#if HOST_BROWSER
324327

325328
gboolean

src/mono/mono/mini/interp/interp.c

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4081,7 +4081,39 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
40814081
}
40824082
ip += 5;
40834083

4084-
goto call;
4084+
InterpMethodCodeType code_type = cmethod->code_type;
4085+
4086+
g_assert (code_type == IMETHOD_CODE_UNKNOWN ||
4087+
code_type == IMETHOD_CODE_INTERP ||
4088+
code_type == IMETHOD_CODE_COMPILED);
4089+
4090+
if (G_UNLIKELY (code_type == IMETHOD_CODE_UNKNOWN)) {
4091+
// FIXME push/pop LMF
4092+
MonoMethodSignature *sig = mono_method_signature_internal (cmethod->method);
4093+
if (mono_interp_jit_call_supported (cmethod->method, sig))
4094+
code_type = IMETHOD_CODE_COMPILED;
4095+
else
4096+
code_type = IMETHOD_CODE_INTERP;
4097+
cmethod->code_type = code_type;
4098+
}
4099+
4100+
if (code_type == IMETHOD_CODE_INTERP) {
4101+
4102+
goto call;
4103+
4104+
} else if (code_type == IMETHOD_CODE_COMPILED) {
4105+
frame->state.ip = ip;
4106+
error_init_reuse (error);
4107+
do_jit_call (context, (stackval*)(locals + return_offset), (stackval*)(locals + call_args_offset), frame, cmethod, error);
4108+
if (!is_ok (error)) {
4109+
MonoException *call_ex = interp_error_convert_to_exception (frame, error, ip);
4110+
THROW_EX (call_ex, ip);
4111+
}
4112+
4113+
CHECK_RESUME_STATE (context);
4114+
}
4115+
4116+
MINT_IN_BREAK;
40854117
}
40864118
MINT_IN_CASE(MINT_CALLI) {
40874119
gboolean need_unbox;
@@ -8595,6 +8627,31 @@ interp_sufficient_stack (gsize size)
85958627
return (context->stack_pointer + size) < (context->stack_start + INTERP_STACK_SIZE);
85968628
}
85978629

8630+
gboolean
8631+
interp_jit_call_can_be_supported (MonoMethod *method, MonoMethodSignature *sig, gboolean is_llvm_only)
8632+
{
8633+
if (sig->param_count > 10)
8634+
return FALSE;
8635+
if (sig->pinvoke)
8636+
return FALSE;
8637+
if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
8638+
return FALSE;
8639+
if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
8640+
return FALSE;
8641+
if (!is_llvm_only && method->is_inflated)
8642+
return FALSE;
8643+
if (method->string_ctor)
8644+
return FALSE;
8645+
if (method->wrapper_type != MONO_WRAPPER_NONE)
8646+
return FALSE;
8647+
8648+
if (method->flags & METHOD_ATTRIBUTE_REQSECOBJ)
8649+
/* Used to mark methods containing StackCrawlMark locals */
8650+
return FALSE;
8651+
8652+
return TRUE;
8653+
}
8654+
85988655
static void
85998656
interp_cleanup (void)
86008657
{

src/mono/mono/mini/interp/transform.c

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,23 +1213,7 @@ mono_interp_jit_call_supported (MonoMethod *method, MonoMethodSignature *sig)
12131213
{
12141214
GSList *l;
12151215

1216-
if (sig->param_count > 10)
1217-
return FALSE;
1218-
if (sig->pinvoke)
1219-
return FALSE;
1220-
if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
1221-
return FALSE;
1222-
if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
1223-
return FALSE;
1224-
if (!mono_llvm_only && method->is_inflated)
1225-
return FALSE;
1226-
if (method->string_ctor)
1227-
return FALSE;
1228-
if (method->wrapper_type != MONO_WRAPPER_NONE)
1229-
return FALSE;
1230-
1231-
if (method->flags & METHOD_ATTRIBUTE_REQSECOBJ)
1232-
/* Used to mark methods containing StackCrawlMark locals */
1216+
if (!interp_jit_call_can_be_supported (method, sig, mono_llvm_only))
12331217
return FALSE;
12341218

12351219
if (mono_aot_only && m_class_get_image (method->klass)->aot_module && !(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
@@ -2991,6 +2975,10 @@ interp_inline_method (TransformData *td, MonoMethod *target_method, MonoMethodHe
29912975
int nargs = csignature->param_count + !!csignature->hasthis;
29922976
InterpInst *prev_last_ins;
29932977

2978+
if (header->code_size == 0)
2979+
/* IL stripped */
2980+
return FALSE;
2981+
29942982
if (csignature->is_inflated)
29952983
generic_context = mono_method_get_context (target_method);
29962984
else {

src/mono/sample/HelloWorld/HelloWorld.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
LibraryFormat="$(_AotLibraryFormat)"
2727
Assemblies="@(AotInputAssemblies)"
2828
OutputDir="$(PublishDir)"
29-
CollectCompiledMethods="$(StripILCode)"
30-
CompiledMethodsOutputDirectory="$(CompiledMethodsOutputDirectory)"
29+
CollectTrimmingEligibleMethods="$(StripILCode)"
30+
TrimmingEligibleMethodsOutputDirectory="$(TrimmingEligibleMethodsOutputDirectory)"
3131
IntermediateOutputPath="$(IntermediateOutputPath)"
3232
UseAotDataFile="$(UseAotDataFile)"
3333
MibcProfilePath="$(MibcProfilePath)"

src/mono/sample/HelloWorld/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ TARGET_OS?=$(shell . $(TOP)eng/native/init-os-and-arch.sh && echo $${os})
88
AOT?=false
99
USE_LLVM?=false
1010
StripILCode?=false
11-
CompiledMethodsOutputDirectory?= #<path-to-a-writable-directory>
11+
TrimmingEligibleMethodsOutputDirectory?= #<path-to-a-writable-directory>
1212

1313
#MIBC_PROFILE_PATH=<path-to-mibc-for-sample>
1414

@@ -21,7 +21,7 @@ publish:
2121
/p:RunAOTCompilation=$(AOT) \
2222
/p:MonoEnableLLVM=$(USE_LLVM) \
2323
/p:StripILCode=$(StripILCode) \
24-
/p:CompiledMethodsOutputDirectory=$(CompiledMethodsOutputDirectory) \
24+
/p:TrimmingEligibleMethodsOutputDirectory=$(TrimmingEligibleMethodsOutputDirectory) \
2525
'/p:MibcProfilePath="$(MIBC_PROFILE_PATH)"' \
2626
/bl
2727

src/mono/wasm/build/WasmApp.InTree.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<Project>
22
<!-- This depends on the root Directory.Build.targets imported this file -->
33
<UsingTask TaskName="MonoAOTCompiler" AssemblyFile="$(MonoAOTCompilerTasksAssemblyPath)" />
4+
<UsingTask TaskName="ILStrip" AssemblyFile="$(MonoTargetsTasksAssemblyPath)" />
45
<UsingTask TaskName="RuntimeConfigParserTask" AssemblyFile="$(MonoTargetsTasksAssemblyPath)" />
56

67
<!-- 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 -->

0 commit comments

Comments
 (0)