Skip to content

Commit

Permalink
[mono][interp] Keep delegate alive during invocation (#100832) (#102159)
Browse files Browse the repository at this point in the history
When invoking a delegate, we were overwritting the stack slot containing the delegate object reference. In the case of invoking a delegate for a dynamic method, we were running into issues when the delegate object is collected while the method is executed because the method code is also discarded.
  • Loading branch information
BrzVlad authored May 29, 2024
1 parent 48a9496 commit 7b08fa8
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/mono/mono/mini/interp/interp-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ struct InterpMethod {
unsigned int hasthis; // boolean
MonoProfilerCallInstrumentationFlags prof_flags;
InterpMethodCodeType code_type;
int ref_slot_offset; // GC visible pointer slot
#ifdef ENABLE_EXPERIMENT_TIERED
MiniTieredCounter tiered_counter;
#endif
Expand Down
3 changes: 3 additions & 0 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -4047,6 +4047,9 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
}
cmethod = del_imethod;
if (!is_multicast) {
int ref_slot_offset = frame->imethod->ref_slot_offset;
if (ref_slot_offset >= 0)
LOCAL_VAR (ref_slot_offset, gpointer) = del;
if (cmethod->param_count == param_count + 1) {
// Target method is static but the delegate has a target object. We handle
// this separately from the case below, because, for these calls, the instance
Expand Down
21 changes: 21 additions & 0 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,17 @@ create_interp_dummy_var (TransformData *td)
td->locals [td->dummy_var].flags = INTERP_LOCAL_FLAG_GLOBAL;
}

static int alloc_global_var_offset (TransformData *td, int var);

static void
interp_create_ref_handle_var (TransformData *td)
{
int var = create_interp_local_explicit (td, m_class_get_byval_arg (mono_defaults.int_class), sizeof (gpointer));
td->locals [var].flags = INTERP_LOCAL_FLAG_GLOBAL;
alloc_global_var_offset (td, var);
td->ref_handle_var = var;
}

static int
get_tos_offset (TransformData *td)
{
Expand Down Expand Up @@ -3798,6 +3809,10 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
td->last_ins->data [0] = get_data_item_index_imethod (td, mono_interp_get_imethod (target_method));
} else {
if (is_delegate_invoke) {
// MINT_CALL_DELEGATE will store the delegate object into this slot so it is kept alive
// while the method is invoked
if (td->ref_handle_var == -1)
interp_create_ref_handle_var (td);
interp_add_ins (td, MINT_CALL_DELEGATE);
interp_ins_set_dreg (td->last_ins, dreg);
interp_ins_set_sreg (td->last_ins, MINT_CALL_ARGS_SREG);
Expand Down Expand Up @@ -11149,6 +11164,7 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG
td->n_data_items = 0;
td->max_data_items = 0;
td->dummy_var = -1;
td->ref_handle_var = -1;
td->data_items = NULL;
td->data_hash = g_hash_table_new (NULL, NULL);
#ifdef ENABLE_EXPERIMENT_TIERED
Expand Down Expand Up @@ -11287,6 +11303,11 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG
mono_interp_register_imethod_data_items (rtm->data_items, td->imethod_items);
rtm->patchpoint_data = td->patchpoint_data;

if (td->ref_handle_var != -1)
rtm->ref_slot_offset = td->locals [td->ref_handle_var].offset;
else
rtm->ref_slot_offset = -1;

/* Save debug info */
interp_save_debug_info (rtm, header, td, td->line_numbers);

Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/interp/transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ typedef struct
gint32 max_stack_size;
InterpLocal *locals;
int dummy_var;
int ref_handle_var;
int *local_ref_count;
unsigned int il_locals_offset;
unsigned int il_locals_size;
Expand Down

0 comments on commit 7b08fa8

Please sign in to comment.