diff --git a/src/mono/mono/mini/interp/interp-internals.h b/src/mono/mono/mini/interp/interp-internals.h index 465fd20240fa4..8db776412fef2 100644 --- a/src/mono/mono/mini/interp/interp-internals.h +++ b/src/mono/mono/mini/interp/interp-internals.h @@ -97,6 +97,10 @@ typedef enum { #define PROFILE_INTERP 0 +#define INTERP_IMETHOD_TAG_UNBOX(im) ((gpointer)((mono_u)(im) | 1)) +#define INTERP_IMETHOD_IS_TAGGED_UNBOX(im) ((mono_u)(im) & 1) +#define INTERP_IMETHOD_UNTAG_UNBOX(im) ((InterpMethod*)((mono_u)(im) & ~1)) + /* * Structure representing a method transformed for the interpreter */ @@ -125,6 +129,7 @@ struct InterpMethod { MonoType **param_types; MonoJitInfo *jinfo; MonoFtnDesc *ftndesc; + MonoFtnDesc *ftndesc_unbox; guint32 locals_size; guint32 alloca_size; diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 61b685cb307c8..7ad368990b162 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -1679,7 +1679,7 @@ interp_init_delegate (MonoDelegate *del, MonoError *error) /* Convert a function pointer for a managed method to an InterpMethod* */ static InterpMethod* -ftnptr_to_imethod (gpointer addr) +ftnptr_to_imethod (gpointer addr, gboolean *need_unbox) { InterpMethod *imethod; @@ -1690,44 +1690,59 @@ ftnptr_to_imethod (gpointer addr) g_assert (ftndesc); g_assert (ftndesc->method); - imethod = ftndesc->interp_method; - if (!imethod) { + if (!ftndesc->interp_method) { imethod = mono_interp_get_imethod (ftndesc->method, error); mono_error_assert_ok (error); mono_memory_barrier (); + // FIXME Handle unboxing here ? ftndesc->interp_method = imethod; } + *need_unbox = INTERP_IMETHOD_IS_TAGGED_UNBOX (ftndesc->interp_method); + imethod = INTERP_IMETHOD_UNTAG_UNBOX (ftndesc->interp_method); } else { /* Function pointers are represented by their InterpMethod */ - imethod = (InterpMethod*)addr; + *need_unbox = INTERP_IMETHOD_IS_TAGGED_UNBOX (addr); + imethod = INTERP_IMETHOD_UNTAG_UNBOX (addr); } return imethod; } static gpointer -imethod_to_ftnptr (InterpMethod *imethod) +imethod_to_ftnptr (InterpMethod *imethod, gboolean need_unbox) { if (mono_llvm_only) { ERROR_DECL (error); /* Function pointers are represented by a MonoFtnDesc structure */ - MonoFtnDesc *ftndesc = imethod->ftndesc; - if (!ftndesc) { - ftndesc = mini_llvmonly_load_method_ftndesc (imethod->method, FALSE, FALSE, error); + MonoFtnDesc **ftndesc_p; + if (need_unbox) + ftndesc_p = &imethod->ftndesc_unbox; + else + ftndesc_p = &imethod->ftndesc; + if (!*ftndesc_p) { + MonoFtnDesc *ftndesc = mini_llvmonly_load_method_ftndesc (imethod->method, FALSE, need_unbox, error); mono_error_assert_ok (error); + if (need_unbox) + ftndesc->interp_method = INTERP_IMETHOD_TAG_UNBOX (imethod); + else + ftndesc->interp_method = imethod; mono_memory_barrier (); - imethod->ftndesc = ftndesc; + *ftndesc_p = ftndesc; } - return ftndesc; + return *ftndesc_p; } else { - return imethod; + if (need_unbox) + return INTERP_IMETHOD_TAG_UNBOX (imethod); + else + return imethod; } } static void interp_delegate_ctor (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoError *error) { + gboolean need_unbox; /* addr is the result of an LDFTN opcode */ - InterpMethod *imethod = ftnptr_to_imethod (addr); + InterpMethod *imethod = ftnptr_to_imethod (addr, &need_unbox); if (!(imethod->method->flags & METHOD_ATTRIBUTE_STATIC)) { MonoMethod *invoke = mono_get_delegate_invoke_internal (mono_handle_class (this_obj)); @@ -3484,12 +3499,10 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs goto call; } MINT_IN_CASE(MINT_CALLI) { - MonoMethodSignature *csignature; - - csignature = (MonoMethodSignature*)frame->imethod->data_items [ip [4]]; + gboolean need_unbox; /* In mixed mode, stay in the interpreter for simplicity even if there is an AOT version of the callee */ - cmethod = ftnptr_to_imethod (LOCAL_VAR (ip [2], gpointer)); + cmethod = ftnptr_to_imethod (LOCAL_VAR (ip [2], gpointer), &need_unbox); if (cmethod->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) { cmethod = mono_interp_get_imethod (mono_marshal_get_native_wrapper (cmethod->method, FALSE, FALSE), error); @@ -3499,15 +3512,11 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs return_offset = ip [1]; call_args_offset = ip [3]; - if (csignature->hasthis) { + if (need_unbox) { MonoObject *this_arg = LOCAL_VAR (call_args_offset, MonoObject*); - - if (m_class_is_valuetype (this_arg->vtable->klass)) { - gpointer unboxed = mono_object_unbox_internal (this_arg); - LOCAL_VAR (call_args_offset, gpointer) = unboxed; - } + LOCAL_VAR (call_args_offset, gpointer) = mono_object_unbox_internal (this_arg); } - ip += 5; + ip += 4; goto call; } @@ -6508,17 +6517,18 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_LDFTN) { InterpMethod *m = (InterpMethod*)frame->imethod->data_items [ip [2]]; - LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (m); + LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (m, FALSE); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_LDVIRTFTN) { - InterpMethod *m = (InterpMethod*)frame->imethod->data_items [ip [3]]; + InterpMethod *virtual_method = (InterpMethod*)frame->imethod->data_items [ip [3]]; MonoObject *o = LOCAL_VAR (ip [2], MonoObject*); NULL_CHECK (o); - m = get_virtual_method (m, o->vtable); - LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (m); + InterpMethod *res_method = get_virtual_method (virtual_method, o->vtable); + gboolean need_unbox = m_class_is_valuetype (res_method->method->klass) && !m_class_is_valuetype (virtual_method->method->klass); + LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (res_method, need_unbox); ip += 4; MINT_IN_BREAK; } @@ -6529,7 +6539,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; InterpMethod *m = mono_interp_get_imethod (cmethod, error); mono_error_assert_ok (error); - LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (m); + LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (m, FALSE); ip += 3; MINT_IN_BREAK; } @@ -6711,7 +6721,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; mono_error_assert_ok (error); } g_assert (del->interp_method); - LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (del->interp_method); + LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (del->interp_method, FALSE); ip += 3; MINT_IN_BREAK; } diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index 9ef942e9d1b25..a274ff2c1b4ad 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -664,7 +664,7 @@ OPDEF(MINT_CALL, "call", 4, 1, 1, MintOpMethodToken) OPDEF(MINT_CALLVIRT, "callvirt", 4, 1, 1, MintOpMethodToken) OPDEF(MINT_CALLVIRT_FAST, "callvirt.fast", 5, 1, 1, MintOpMethodToken) OPDEF(MINT_CALL_DELEGATE, "call.delegate", 5, 1, 1, MintOpTwoShorts) -OPDEF(MINT_CALLI, "calli", 5, 1, 2, MintOpMethodToken) +OPDEF(MINT_CALLI, "calli", 4, 1, 2, MintOpNoArgs) OPDEF(MINT_CALLI_NAT, "calli.nat", 8, 1, 2, MintOpMethodToken) OPDEF(MINT_CALLI_NAT_DYNAMIC, "calli.nat.dynamic", 5, 1, 2, MintOpMethodToken) OPDEF(MINT_CALLI_NAT_FAST, "calli.nat.fast", 7, 1, 2, MintOpMethodToken) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 0e71341d852f5..0196a402d6d0c 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -3511,7 +3511,6 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target interp_add_ins (td, MINT_CALLI); interp_ins_set_dreg (td->last_ins, dreg); interp_ins_set_sregs2 (td->last_ins, fp_sreg, MINT_CALL_ARGS_SREG); - td->last_ins->data [0] = get_data_item_index (td, (void *)csignature); } } else { InterpMethod *imethod = mono_interp_get_imethod (target_method, error); diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index c4bd7def1cbcb..c7ad6d4c5fa76 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -1144,7 +1144,7 @@ typedef struct gpointer addr; gpointer arg; MonoMethod *method; - /* InterpMethod* */ + /* Tagged InterpMethod* */ gpointer interp_method; } MonoFtnDesc; diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 7b090ae247847..320be9692e23c 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1556,9 +1556,6 @@ https://github.com/dotnet/runtime/issues/54396 - - https://github.com/dotnet/runtime/issues/54374 - https://github.com/dotnet/runtime/issues/54381