Skip to content

Commit

Permalink
[mono][interp] Properly handle exceptions thrown by mono_marshal_get_…
Browse files Browse the repository at this point in the history
…native_wrapper (dotnet#110232)

* [mono][interp] Defer calls to mono_marshal_get_native_wrapper at execution

This can end up calling into managed where exceptions can be thrown. Throwing exceptions while method compilation happens in not valid behavior. This follows the same approach from the jit side in mono/mono#20177.

* [mono][interp] Check resume state when returning from method compilation

* [mono][interp] Fix tiering disable condition

We always optimize managed wrappers. If we are attempting to compile and execute a pinvoke method, we will use the m2n wrapper instead. Make sure we check for this when disabling tiering, since swift interop relies on these wrappers to be always optimized.
  • Loading branch information
BrzVlad authored and eduardo-vp committed Dec 4, 2024
1 parent 53ccff6 commit 8ce3c67
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
5 changes: 4 additions & 1 deletion src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,8 +502,9 @@ mono_interp_get_imethod (MonoMethod *method)
imethod->is_invoke = (m_class_get_parent (method->klass) == mono_defaults.multicastdelegate_class) && !strcmp(method->name, "Invoke");
// always optimize code if tiering is disabled
// always optimize wrappers
if (!mono_interp_tiering_enabled () || method->wrapper_type != MONO_WRAPPER_NONE)
if (!mono_interp_tiering_enabled () || method->wrapper_type != MONO_WRAPPER_NONE || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
imethod->optimized = TRUE;

if (imethod->method->string_ctor)
imethod->rtype = m_class_get_byval_arg (mono_defaults.string_class);
else
Expand Down Expand Up @@ -3916,6 +3917,7 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
if (method_entry_ex)
THROW_EX (method_entry_ex, NULL);
EXCEPTION_CHECKPOINT;
CHECK_RESUME_STATE (context);
}

if (!clause_args) {
Expand Down Expand Up @@ -4372,6 +4374,7 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
if (call_ex)
THROW_EX (call_ex, NULL);
EXCEPTION_CHECKPOINT;
CHECK_RESUME_STATE (context);
}

context->stack_pointer = (guchar*)frame->stack + cmethod->alloca_size;
Expand Down
22 changes: 17 additions & 5 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -2691,8 +2691,6 @@ static MonoMethod*
interp_transform_internal_calls (MonoMethod *method, MonoMethod *target_method, MonoMethodSignature *csignature, gboolean is_virtual)
{
if (((method->wrapper_type == MONO_WRAPPER_NONE) || (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)) && target_method != NULL) {
if (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
target_method = mono_marshal_get_native_wrapper (target_method, FALSE, FALSE);
if (!is_virtual && target_method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
target_method = mono_marshal_get_synchronized_wrapper (target_method);

Expand Down Expand Up @@ -3748,9 +3746,19 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
}
}

if (op == -1)
if (op == -1) {
target_method = interp_transform_internal_calls (method, target_method, csignature, is_virtual);

if (((method->wrapper_type == MONO_WRAPPER_NONE) || (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)) && target_method != NULL) {
if (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
// Avoid calling mono_marshal_get_native_wrapper () too early, it might call managed callbacks.
csignature = mono_metadata_signature_dup_mempool (td->mempool, csignature);
csignature->pinvoke = FALSE;
native = FALSE;
}
}
}

if (csignature->call_convention == MONO_CALL_VARARG)
csignature = mono_method_get_signature_checked (target_method, image, token, generic_context, error);

Expand Down Expand Up @@ -9898,16 +9906,20 @@ mono_interp_transform_method (InterpMethod *imethod, ThreadContext *context, Mon
generic_context = &generic_container->context;
}

if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
if ((method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) ||
(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
MonoMethod *nm = NULL;
if (imethod->transformed) {
MONO_PROFILER_RAISE (jit_done, (method, imethod->jinfo));
return;
}

/* assumes all internal calls with an array this are built in... */
if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL && (! mono_method_signature_internal (method)->hasthis || m_class_get_rank (method->klass) == 0)) {
if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL && (! mono_method_signature_internal (method)->hasthis || m_class_get_rank (method->klass) == 0)) ||
(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
nm = mono_marshal_get_native_wrapper (method, FALSE, FALSE);
if (context->has_resume_state)
return;
} else {
const char *name = method->name;
if (m_class_get_parent (method->klass) == mono_defaults.multicastdelegate_class) {
Expand Down

0 comments on commit 8ce3c67

Please sign in to comment.