From 9ddd58a58d14a7bec5ed6eb777c6703c48aca15d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 20 Dec 2021 18:12:38 -0500 Subject: [PATCH] Various WASM AOT changes (#62997) * [mono] Add a mono_dummy_jit_icall_val () icall. This can be used to trace values from AOT code during runtime debugging. * [mono] Avoid adding a try clause to vector alloc wrappers. Previously, a try-catch clause was added to the vector Alloc wrappers to convert the OverflowException thrown by the .ovf opcodes to an OutOfMemoryException. This could cause EH problems on wasm since on wasm no AOTed code should contain clauses, but this wrapper was still AOTed for performance reasons. Instead, add a new CIL opcode to make the .ovf opcodes throw the OutOfMemoryException directly. * Disable inline rgctx fetch in mono_decompose_vtype_opts () as well. It can't handle the new bblocks added by the inline rgctx fetch code. * [mono] Factor out the slow path of Array.Copy () into a separate method. The slowpath contained a try-catch clause, preventing Array.Copy () from being AOTed on WASM. * [mono] Fix assigning a name to LLVM Alloca instructions. * Add a V=1 makefile option to wasm/Makefile. * Add a WasmAotProfilePath build property. --- .../src/System/Array.Mono.cs | 5 +++ src/mono/mono/cil/cil-opcodes.xml | 1 + src/mono/mono/cil/opcode.def | 1 + src/mono/mono/metadata/jit-icall-reg.h | 1 + src/mono/mono/metadata/sgen-mono-ilgen.c | 37 +++---------------- src/mono/mono/mini/decompose.c | 21 ++++++----- src/mono/mono/mini/jit-icalls.c | 5 +++ src/mono/mono/mini/jit-icalls.h | 2 + src/mono/mono/mini/method-to-ir.c | 7 ++++ src/mono/mono/mini/mini-codegen.c | 2 + src/mono/mono/mini/mini-llvm-cpp.cpp | 2 +- src/mono/mono/mini/mini-llvm.c | 2 +- src/mono/mono/mini/mini-runtime.c | 1 + src/mono/mono/mini/mini.h | 5 +++ src/mono/wasm/Makefile | 4 ++ src/mono/wasm/build/WasmApp.Native.targets | 4 +- src/mono/wasm/build/WasmApp.targets | 1 + 17 files changed, 57 insertions(+), 44 deletions(-) diff --git a/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs index 94cb9eb7fee..a8bf7fdc42b 100644 --- a/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs @@ -144,6 +144,11 @@ private static void Copy(Array sourceArray, int sourceIndex, Array destinationAr if (FastCopy(sourceArray, sourceIndex, destinationArray, destinationIndex, length)) return; + CopySlow(sourceArray, sourceIndex, destinationArray, destinationIndex, length, reliable); + } + + private static void CopySlow(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable) + { int source_pos = sourceIndex - sourceArray.GetLowerBound(0); int dest_pos = destinationIndex - destinationArray.GetLowerBound(0); diff --git a/src/mono/mono/cil/cil-opcodes.xml b/src/mono/mono/cil/cil-opcodes.xml index 50b70144d16..5b047e47e1e 100644 --- a/src/mono/mono/cil/cil-opcodes.xml +++ b/src/mono/mono/cil/cil-opcodes.xml @@ -327,4 +327,5 @@ + diff --git a/src/mono/mono/cil/opcode.def b/src/mono/mono/cil/opcode.def index 4b0769de95e..47bccb295e9 100644 --- a/src/mono/mono/cil/opcode.def +++ b/src/mono/mono/cil/opcode.def @@ -327,6 +327,7 @@ OPDEF(CEE_MONO_RETHROW, "mono_rethrow", PopRef, Push0, InlineNone, 0, 2, 0xF0, 0 OPDEF(CEE_MONO_GET_SP, "mono_get_sp", Pop0, PushI, InlineNone, 0, 2, 0xF0, 0x20, NEXT) OPDEF(CEE_MONO_METHODCONST, "mono_methodconst", Pop0, PushI, InlineI, 0, 2, 0xF0, 0x21, NEXT) OPDEF(CEE_MONO_PINVOKE_ADDR_CACHE, "mono_pinvoke_addr_cache", Pop0, PushI, InlineI, 0, 2, 0xF0, 0x22, NEXT) +OPDEF(CEE_MONO_REMAP_OVF_EXC, "mono_remap_ovf_exc", Pop0, Push0, InlineI, 0, 2, 0xF0, 0x23, NEXT) #ifndef OPALIAS #define _MONO_CIL_OPALIAS_DEFINED_ #define OPALIAS(a,s,r) diff --git a/src/mono/mono/metadata/jit-icall-reg.h b/src/mono/mono/metadata/jit-icall-reg.h index 577a14eb656..804431515d1 100644 --- a/src/mono/mono/metadata/jit-icall-reg.h +++ b/src/mono/mono/metadata/jit-icall-reg.h @@ -181,6 +181,7 @@ MONO_JIT_ICALL (mono_delegate_end_invoke) \ MONO_JIT_ICALL (mono_delegate_to_ftnptr) \ MONO_JIT_ICALL (mono_domain_get) \ MONO_JIT_ICALL (mono_dummy_jit_icall) \ +MONO_JIT_ICALL (mono_dummy_jit_icall_val) \ MONO_JIT_ICALL (mono_exception_from_token) \ MONO_JIT_ICALL (mono_fill_class_rgctx) \ MONO_JIT_ICALL (mono_fill_method_rgctx) \ diff --git a/src/mono/mono/metadata/sgen-mono-ilgen.c b/src/mono/mono/metadata/sgen-mono-ilgen.c index f9887161d37..aa5e034dbc6 100644 --- a/src/mono/mono/metadata/sgen-mono-ilgen.c +++ b/src/mono/mono/metadata/sgen-mono-ilgen.c @@ -233,11 +233,7 @@ emit_managed_allocator_ilgen (MonoMethodBuilder *mb, gboolean slowpath, gboolean mono_mb_emit_byte (mb, CEE_CONV_I); mono_mb_emit_stloc (mb, size_var); } else if (atype == ATYPE_VECTOR) { - ERROR_DECL (error); - MonoExceptionClause *clause; - int pos, pos_leave, pos_error; - MonoClass *oom_exc_class; - MonoMethod *ctor; + int pos, pos_error; /* * n > MONO_ARRAY_MAX_INDEX => OutOfMemoryException @@ -262,9 +258,6 @@ emit_managed_allocator_ilgen (MonoMethodBuilder *mb, gboolean slowpath, gboolean mono_mb_patch_short_branch (mb, pos); - clause = (MonoExceptionClause *)mono_image_alloc0 (mono_defaults.corlib, sizeof (MonoExceptionClause)); - clause->try_offset = mono_mb_get_label (mb); - /* vtable->klass->sizes.element_size */ mono_mb_emit_ldarg (mb, 0); mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoVTable, klass)); @@ -279,35 +272,15 @@ emit_managed_allocator_ilgen (MonoMethodBuilder *mb, gboolean slowpath, gboolean /* * n */ mono_mb_emit_ldarg (mb, 1); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_op (mb, CEE_MONO_REMAP_OVF_EXC, (gpointer)"OutOfMemoryException"); mono_mb_emit_byte (mb, CEE_MUL_OVF_UN); /* + sizeof (MonoArray) */ mono_mb_emit_icon (mb, MONO_SIZEOF_MONO_ARRAY); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_op (mb, CEE_MONO_REMAP_OVF_EXC, (gpointer)"OutOfMemoryException"); mono_mb_emit_byte (mb, CEE_ADD_OVF_UN); mono_mb_emit_stloc (mb, size_var); - - pos_leave = mono_mb_emit_branch (mb, CEE_LEAVE); - - /* catch */ - clause->flags = MONO_EXCEPTION_CLAUSE_NONE; - clause->try_len = mono_mb_get_pos (mb) - clause->try_offset; - clause->data.catch_class = mono_class_load_from_name (mono_defaults.corlib, - "System", "OverflowException"); - clause->handler_offset = mono_mb_get_label (mb); - - oom_exc_class = mono_class_load_from_name (mono_defaults.corlib, - "System", "OutOfMemoryException"); - ctor = mono_class_get_method_from_name_checked (oom_exc_class, ".ctor", 0, 0, error); - mono_error_assert_ok (error); - g_assert (ctor); - - mono_mb_emit_byte (mb, CEE_POP); - mono_mb_emit_op (mb, CEE_NEWOBJ, ctor); - mono_mb_emit_byte (mb, CEE_THROW); - - clause->handler_len = mono_mb_get_pos (mb) - clause->handler_offset; - mono_mb_set_clauses (mb, 1, clause); - mono_mb_patch_branch (mb, pos_leave); - /* end catch */ } else if (atype == ATYPE_STRING) { /* * a string allocator method takes the args: (vtable, len) diff --git a/src/mono/mono/mini/decompose.c b/src/mono/mono/mini/decompose.c index 46de11de21c..efc8bfd6f06 100644 --- a/src/mono/mono/mini/decompose.c +++ b/src/mono/mono/mini/decompose.c @@ -81,7 +81,7 @@ decompose_long_opcode (MonoCompile *cfg, MonoInst *ins, MonoInst **repl_ins) else opcode = OP_ADDCC; EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2); - MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException"); + MONO_EMIT_NEW_COND_EXC (cfg, OV, ins->inst_exc_name); NULLIFY_INS (ins); break; } @@ -95,7 +95,7 @@ decompose_long_opcode (MonoCompile *cfg, MonoInst *ins, MonoInst **repl_ins) else opcode = OP_ADDCC; EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2); - MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException"); + MONO_EMIT_NEW_COND_EXC (cfg, C, ins->inst_exc_name); NULLIFY_INS (ins); break; } @@ -110,7 +110,7 @@ decompose_long_opcode (MonoCompile *cfg, MonoInst *ins, MonoInst **repl_ins) else opcode = OP_SUBCC; EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2); - MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException"); + MONO_EMIT_NEW_COND_EXC (cfg, OV, ins->inst_exc_name); NULLIFY_INS (ins); break; } @@ -124,7 +124,7 @@ decompose_long_opcode (MonoCompile *cfg, MonoInst *ins, MonoInst **repl_ins) else opcode = OP_SUBCC; EMIT_NEW_BIALU (cfg, repl, opcode, ins->dreg, ins->sreg1, ins->sreg2); - MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException"); + MONO_EMIT_NEW_COND_EXC (cfg, C, ins->inst_exc_name); NULLIFY_INS (ins); break; } @@ -327,7 +327,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) if (COMPILE_LLVM (cfg)) break; ins->opcode = OP_IADDCC; - MONO_EMIT_NEW_COND_EXC (cfg, IC, "OverflowException"); + MONO_EMIT_NEW_COND_EXC (cfg, IC, ins->inst_exc_name); break; case OP_ISUB_OVF: if (COMPILE_LLVM (cfg)) @@ -859,25 +859,25 @@ mono_decompose_long_opts (MonoCompile *cfg) /* ADC sets the condition code */ MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); - MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException"); + MONO_EMIT_NEW_COND_EXC (cfg, OV, tree->inst_exc_name); break; case OP_LADD_OVF_UN: /* ADC sets the condition code */ MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); - MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException"); + MONO_EMIT_NEW_COND_EXC (cfg, C, tree->inst_exc_name); break; case OP_LSUB_OVF: /* SBB sets the condition code */ MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); - MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException"); + MONO_EMIT_NEW_COND_EXC (cfg, OV, tree->inst_exc_name); break; case OP_LSUB_OVF_UN: /* SBB sets the condition code */ MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); - MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException"); + MONO_EMIT_NEW_COND_EXC (cfg, C, tree->inst_exc_name); break; case OP_LAND: MONO_EMIT_NEW_BIALU (cfg, OP_IAND, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); @@ -1445,8 +1445,11 @@ mono_decompose_vtype_opts (MonoCompile *cfg) src->klass = ins->klass; src->dreg = ins->sreg1; } + + cfg->disable_inline_rgctx_fetch = TRUE; MonoInst *tmp = mini_emit_box (cfg, src, ins->klass, mini_class_check_context_used (cfg, ins->klass)); g_assert (tmp); + cfg->disable_inline_rgctx_fetch = FALSE; MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, tmp->dreg); diff --git a/src/mono/mono/mini/jit-icalls.c b/src/mono/mono/mini/jit-icalls.c index a0078c45656..b55fe7fc2d7 100644 --- a/src/mono/mono/mini/jit-icalls.c +++ b/src/mono/mono/mini/jit-icalls.c @@ -1622,3 +1622,8 @@ void mono_dummy_jit_icall (void) { } + +void +mono_dummy_jit_icall_val (gpointer val) +{ +} diff --git a/src/mono/mono/mini/jit-icalls.h b/src/mono/mono/mini/jit-icalls.h index 646e888b471..1df30a95e73 100644 --- a/src/mono/mono/mini/jit-icalls.h +++ b/src/mono/mono/mini/jit-icalls.h @@ -229,4 +229,6 @@ ICALL_EXPORT void mono_throw_invalid_program (const char *msg); ICALL_EXPORT void mono_dummy_jit_icall (void); +ICALL_EXPORT void mono_dummy_jit_icall_val (gpointer ptr); + #endif /* __MONO_JIT_ICALLS_H__ */ diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index d1da9506106..85ca8d26270 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -524,6 +524,7 @@ add_widen_op (MonoCompile *cfg, MonoInst *ins, MonoInst **arg1_ref, MonoInst **a ins->sreg2 = sp [1]->dreg; \ type_from_op (cfg, ins, sp [0], sp [1]); \ CHECK_TYPE (ins); \ + if (ovf_exc) ins->inst_exc_name = ovf_exc; else ins->inst_exc_name = "OverflowException"; ovf_exc = NULL; \ /* Have to insert a widening op */ \ add_widen_op (cfg, ins, &sp [0], &sp [1]); \ ins->dreg = alloc_dreg ((cfg), (MonoStackType)(ins)->type); \ @@ -6149,6 +6150,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MonoDebugMethodInfo *minfo; MonoBitSet *seq_point_locs = NULL; MonoBitSet *seq_point_set_locs = NULL; + const char *ovf_exc = NULL; gboolean emitted_funccall_seq_point = FALSE; gboolean detached_before_ret = FALSE; gboolean ins_has_side_effect; @@ -11084,6 +11086,11 @@ mono_ldptr: *sp++ = ins; break; } + case MONO_CEE_MONO_REMAP_OVF_EXC: + /* Remap the exception thrown by the next _OVF opcode */ + g_assert (method->wrapper_type != MONO_WRAPPER_NONE); + ovf_exc = (const char*)mono_method_get_wrapper_data (method, token); + break; case MONO_CEE_ARGLIST: { /* somewhat similar to LDTOKEN */ diff --git a/src/mono/mono/mini/mini-codegen.c b/src/mono/mono/mini/mini-codegen.c index 44a60604b94..77464dcf88c 100644 --- a/src/mono/mono/mini/mini-codegen.c +++ b/src/mono/mono/mini/mini-codegen.c @@ -2716,6 +2716,8 @@ mini_exception_id_by_name (const char *name) return MONO_EXC_ARGUMENT; if (strcmp (name, "ArgumentOutOfRangeException") == 0) return MONO_EXC_ARGUMENT_OUT_OF_RANGE; + if (strcmp (name, "OutOfMemoryException") == 0) + return MONO_EXC_ARGUMENT_OUT_OF_MEMORY; g_error ("Unknown intrinsic exception %s\n", name); return -1; } diff --git a/src/mono/mono/mini/mini-llvm-cpp.cpp b/src/mono/mono/mini/mini-llvm-cpp.cpp index d2bf4eb7c77..fc87c556ae3 100644 --- a/src/mono/mono/mini/mini-llvm-cpp.cpp +++ b/src/mono/mono/mini/mini-llvm-cpp.cpp @@ -105,7 +105,7 @@ mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, LLVMValueRef Arr auto sz = unwrap (ArraySize); auto b = unwrap (builder); auto ins = alignment > 0 - ? b->Insert (new AllocaInst (ty, 0, sz, to_align (alignment), Name)) + ? b->Insert (new AllocaInst (ty, 0, sz, to_align (alignment)), Name) : b->CreateAlloca (ty, 0, sz, Name); return wrap (ins); } diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 4193900b324..75c45652b06 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -7287,7 +7287,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) val = call_intrins (ctx, intrins, args, ""); values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, dname); ovf = LLVMBuildExtractValue (builder, val, 1, ""); - emit_cond_system_exception (ctx, bb, "OverflowException", ovf, FALSE); + emit_cond_system_exception (ctx, bb, ins->inst_exc_name, ovf, FALSE); if (!ctx_ok (ctx)) break; builder = ctx->builder; diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 83078470df3..0841d15ae72 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -4919,6 +4919,7 @@ register_icalls (void) register_icall (mono_throw_platform_not_supported, mono_icall_sig_void, FALSE); register_icall (mono_throw_invalid_program, mono_icall_sig_void_ptr, FALSE); register_icall_no_wrapper (mono_dummy_jit_icall, mono_icall_sig_void); + //register_icall_no_wrapper (mono_dummy_jit_icall_val, mono_icall_sig_void_ptr); register_icall_with_wrapper (mono_monitor_enter_internal, mono_icall_sig_int32_obj); register_icall_with_wrapper (mono_monitor_enter_v4_internal, mono_icall_sig_void_obj_ptr); diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index b693081d631..e671ca86b11 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -757,6 +757,7 @@ struct MonoInst { int *phi_args; MonoCallInst *call_inst; GList *exception_clauses; + const char *exc_name; } op [2]; gint64 i8const; double r8const; @@ -908,6 +909,9 @@ enum { #define inst_newa_len data.op[0].src #define inst_newa_class data.op[1].klass +/* In _OVF opcodes */ +#define inst_exc_name data.op[0].exc_name + #define inst_var data.op[0].var #define inst_vtype data.op[1].vtype /* in branch instructions */ @@ -1991,6 +1995,7 @@ enum { MONO_EXC_ARRAY_TYPE_MISMATCH, MONO_EXC_ARGUMENT, MONO_EXC_ARGUMENT_OUT_OF_RANGE, + MONO_EXC_ARGUMENT_OUT_OF_MEMORY, MONO_EXC_INTRINS_NUM }; diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index d3f9b3bf08c..d171b9395a7 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -3,6 +3,10 @@ TOP=$(realpath $(CURDIR)/../../..) escape_quote = $(subst ",\",$(1)) +ifneq ($(V),) +MSBUILD_ARGS+=/p:MonoVerboseBuild=true +endif + DOTNET=$(TOP)/dotnet.sh JSVU=$(HOME)/.jsvu CHROMEDRIVER?=$(HOME)/.chromedriver diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets index ea282f9638c..6fb3e5beda1 100644 --- a/src/mono/wasm/build/WasmApp.Native.targets +++ b/src/mono/wasm/build/WasmApp.Native.targets @@ -502,6 +502,7 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_ + <_AotInputAssemblies Include="@(_WasmAssembliesInternal)"> @@ -561,7 +562,8 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_ CacheFilePath="$(_AOTCompilerCacheFile)" LLVMDebug="dwarfdebug" LLVMPath="$(EmscriptenUpstreamBinPath)" - IntermediateOutputPath="$(_WasmIntermediateOutputPath)"> + IntermediateOutputPath="$(_WasmIntermediateOutputPath)" + AotProfilePath="@(AotProfilePath)"> diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 1df620145be..145e5c8f7ee 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -61,6 +61,7 @@ - $(WasmBuildOnlyAfterPublish) - Causes relinking to be done only for Publish. Defaults to false. - $(RunAOTCompilationAfterBuild) - Run AOT compilation even after Build. By default, it is run only for publish. Defaults to false. + - $(WasmAotProfilePath) - Path to an AOT profile file. Public items: - @(WasmExtraFilesToDeploy) - Files to copy to $(WasmAppDir). -- GitLab