未验证 提交 9ddd58a5 编写于 作者: Z Zoltan Varga 提交者: GitHub

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.
上级 192db36c
......@@ -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);
......
......@@ -327,4 +327,5 @@
<opcode name="mono_get_sp" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x20" flow="next" />
<opcode name="mono_methodconst" input="Pop0" output="PushI" args="InlineI" o1="0xF0" o2="0x21" flow="next" />
<opcode name="mono_pinvoke_addr_cache" input="Pop0" output="PushI" args="InlineI" o1="0xF0" o2="0x22" flow="next" />
<opcode name="mono_remap_ovf_exc" input="Pop0" output="Push0" args="InlineI" o1="0xF0" o2="0x23" flow="next" />
</opdesc>
......@@ -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)
......
......@@ -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) \
......
......@@ -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)
......
......@@ -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);
......
......@@ -1622,3 +1622,8 @@ void
mono_dummy_jit_icall (void)
{
}
void
mono_dummy_jit_icall_val (gpointer val)
{
}
......@@ -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__ */
......@@ -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 */
......
......@@ -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;
}
......
......@@ -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);
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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
};
......
......@@ -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
......
......@@ -502,6 +502,7 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_
<MonoAOTCompilerDefaultAotArguments Include="static" />
<MonoAOTCompilerDefaultAotArguments Include="direct-icalls" />
<MonoAOTCompilerDefaultAotArguments Include="deterministic" />
<AotProfilePath Include="$(WasmAotProfilePath)"/>
</ItemGroup>
<ItemGroup>
<_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)">
<Output TaskParameter="CompiledAssemblies" ItemName="_WasmAssembliesInternal" />
<Output TaskParameter="FileWrites" ItemName="FileWrites" />
......
......@@ -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).
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册