Skip to content

Commit 49f9f7a

Browse files
authored
[mono][interp] Fix calling of static delegates with simd arguments (#92927)
* [mono][interp] Small refactoring to make the code clearer Previous code was checking if we should have already pushed a dreg, to compute the correct position of the argument on the stack. Save pointer to args directly instead. * [mono][interp] Fix calling of static delegates with simd arguments If we do a delegate call that translates to a static call, the delegate pointer that was passed needs to be skipped and we need to pass the actual arguments. However, the following arguments might not come immediately after the delegate pointer, if the first argument is simd aligned. Pass this information to MINT_CALL_DELEGATE so the correct offset of the arguments can be computed. * [mono][interp] Don't pass csignature to MINT_CALL_DELEGATE Pass param_count directly
1 parent f37e653 commit 49f9f7a

File tree

3 files changed

+18
-9
lines changed

3 files changed

+18
-9
lines changed

src/mono/mono/mini/interp/interp.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3983,9 +3983,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
39833983
MINT_IN_BREAK;
39843984
}
39853985
MINT_IN_CASE(MINT_CALL_DELEGATE) {
3986-
// FIXME We don't need to encode the whole signature, just param_count
3987-
MonoMethodSignature *csignature = (MonoMethodSignature*)frame->imethod->data_items [ip [4]];
3988-
int param_count = csignature->param_count;
39893986
return_offset = ip [1];
39903987
call_args_offset = ip [2];
39913988
MonoDelegate *del = LOCAL_VAR (call_args_offset, MonoDelegate*);
@@ -4031,6 +4028,7 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
40314028
}
40324029
cmethod = del_imethod;
40334030
if (!is_multicast) {
4031+
int param_count = ip [4];
40344032
if (cmethod->param_count == param_count + 1) {
40354033
// Target method is static but the delegate has a target object. We handle
40364034
// this separately from the case below, because, for these calls, the instance
@@ -4049,10 +4047,10 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
40494047
} else {
40504048
// skip the delegate pointer for static calls
40514049
// FIXME we could avoid memmove
4052-
memmove (locals + call_args_offset, locals + call_args_offset + MINT_STACK_SLOT_SIZE, ip [3]);
4050+
memmove (locals + call_args_offset, locals + call_args_offset + ip [5], ip [3]);
40534051
}
40544052
}
4055-
ip += 5;
4053+
ip += 6;
40564054

40574055
InterpMethodCodeType code_type = cmethod->code_type;
40584056

src/mono/mono/mini/interp/mintops.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ OPDEF(MINT_ARRAY_ELEMENT_SIZE, "array_element_size", 3, 1, 1, MintOpNoArgs)
688688
/* Calls */
689689
OPDEF(MINT_CALL, "call", 4, 1, 1, MintOpMethodToken)
690690
OPDEF(MINT_CALLVIRT_FAST, "callvirt.fast", 5, 1, 1, MintOpMethodToken)
691-
OPDEF(MINT_CALL_DELEGATE, "call.delegate", 5, 1, 1, MintOpTwoShorts)
691+
OPDEF(MINT_CALL_DELEGATE, "call.delegate", 6, 1, 1, MintOpTwoShorts)
692692
OPDEF(MINT_CALLI, "calli", 4, 1, 2, MintOpNoArgs)
693693
OPDEF(MINT_CALLI_NAT, "calli.nat", 8, 1, 2, MintOpTwoShorts)
694694
OPDEF(MINT_CALLI_NAT_DYNAMIC, "calli.nat.dynamic", 5, 1, 2, MintOpShortInt)

src/mono/mono/mini/interp/transform.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3696,6 +3696,8 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
36963696

36973697
int call_offset = -1;
36983698

3699+
StackInfo *sp_args = td->sp;
3700+
36993701
if (!td->optimized && op == -1) {
37003702
int param_offset;
37013703
if (num_args)
@@ -3776,9 +3778,9 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
37763778
if (num_sregs == 1)
37773779
interp_ins_set_sreg (td->last_ins, first_sreg);
37783780
else if (num_sregs == 2)
3779-
interp_ins_set_sregs2 (td->last_ins, first_sreg, td->sp [!has_dreg].local);
3781+
interp_ins_set_sregs2 (td->last_ins, first_sreg, sp_args [1].local);
37803782
else if (num_sregs == 3)
3781-
interp_ins_set_sregs3 (td->last_ins, first_sreg, td->sp [!has_dreg].local, td->sp [!has_dreg + 1].local);
3783+
interp_ins_set_sregs3 (td->last_ins, first_sreg, sp_args [1].local, sp_args [2].local);
37823784
else
37833785
g_error ("Unsupported opcode");
37843786
}
@@ -3798,7 +3800,16 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
37983800
interp_ins_set_dreg (td->last_ins, dreg);
37993801
interp_ins_set_sreg (td->last_ins, MINT_CALL_ARGS_SREG);
38003802
td->last_ins->data [0] = GUINT32_TO_UINT16 (params_stack_size);
3801-
td->last_ins->data [1] = get_data_item_index (td, (void *)csignature);
3803+
td->last_ins->data [1] = GUINT32_TO_UINT16 (csignature->param_count);
3804+
if (csignature->param_count) {
3805+
// Check if the first arg (after the delegate pointer) is simd
3806+
// In case the delegate represents static method with no target, the instruction
3807+
// needs to be able to access the actual arguments to continue with the call so it
3808+
// needs to know whether there is an empty stack slot between the delegate ptr and the
3809+
// rest of the args
3810+
gboolean first_arg_is_simd = td->locals [sp_args [1].local].flags & INTERP_LOCAL_FLAG_SIMD;
3811+
td->last_ins->data [2] = first_arg_is_simd ? MINT_SIMD_ALIGNMENT : MINT_STACK_SLOT_SIZE;
3812+
}
38023813
} else if (calli) {
38033814
MintICallSig icall_sig = MINT_ICALLSIG_MAX;
38043815
#ifndef MONO_ARCH_HAS_NO_PROPER_MONOCTX

0 commit comments

Comments
 (0)