Skip to content

Commit

Permalink
[mono][interp] Fix calling of static delegates with simd arguments (#…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
BrzVlad authored Oct 6, 2023
1 parent f37e653 commit 49f9f7a
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 9 deletions.
8 changes: 3 additions & 5 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -3983,9 +3983,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_CALL_DELEGATE) {
// FIXME We don't need to encode the whole signature, just param_count
MonoMethodSignature *csignature = (MonoMethodSignature*)frame->imethod->data_items [ip [4]];
int param_count = csignature->param_count;
return_offset = ip [1];
call_args_offset = ip [2];
MonoDelegate *del = LOCAL_VAR (call_args_offset, MonoDelegate*);
Expand Down Expand Up @@ -4031,6 +4028,7 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
}
cmethod = del_imethod;
if (!is_multicast) {
int param_count = ip [4];
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 All @@ -4049,10 +4047,10 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
} else {
// skip the delegate pointer for static calls
// FIXME we could avoid memmove
memmove (locals + call_args_offset, locals + call_args_offset + MINT_STACK_SLOT_SIZE, ip [3]);
memmove (locals + call_args_offset, locals + call_args_offset + ip [5], ip [3]);
}
}
ip += 5;
ip += 6;

InterpMethodCodeType code_type = cmethod->code_type;

Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/mini/interp/mintops.def
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ OPDEF(MINT_ARRAY_ELEMENT_SIZE, "array_element_size", 3, 1, 1, MintOpNoArgs)
/* Calls */
OPDEF(MINT_CALL, "call", 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_CALL_DELEGATE, "call.delegate", 6, 1, 1, MintOpTwoShorts)
OPDEF(MINT_CALLI, "calli", 4, 1, 2, MintOpNoArgs)
OPDEF(MINT_CALLI_NAT, "calli.nat", 8, 1, 2, MintOpTwoShorts)
OPDEF(MINT_CALLI_NAT_DYNAMIC, "calli.nat.dynamic", 5, 1, 2, MintOpShortInt)
Expand Down
17 changes: 14 additions & 3 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -3696,6 +3696,8 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target

int call_offset = -1;

StackInfo *sp_args = td->sp;

if (!td->optimized && op == -1) {
int param_offset;
if (num_args)
Expand Down Expand Up @@ -3776,9 +3778,9 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
if (num_sregs == 1)
interp_ins_set_sreg (td->last_ins, first_sreg);
else if (num_sregs == 2)
interp_ins_set_sregs2 (td->last_ins, first_sreg, td->sp [!has_dreg].local);
interp_ins_set_sregs2 (td->last_ins, first_sreg, sp_args [1].local);
else if (num_sregs == 3)
interp_ins_set_sregs3 (td->last_ins, first_sreg, td->sp [!has_dreg].local, td->sp [!has_dreg + 1].local);
interp_ins_set_sregs3 (td->last_ins, first_sreg, sp_args [1].local, sp_args [2].local);
else
g_error ("Unsupported opcode");
}
Expand All @@ -3798,7 +3800,16 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
interp_ins_set_dreg (td->last_ins, dreg);
interp_ins_set_sreg (td->last_ins, MINT_CALL_ARGS_SREG);
td->last_ins->data [0] = GUINT32_TO_UINT16 (params_stack_size);
td->last_ins->data [1] = get_data_item_index (td, (void *)csignature);
td->last_ins->data [1] = GUINT32_TO_UINT16 (csignature->param_count);
if (csignature->param_count) {
// Check if the first arg (after the delegate pointer) is simd
// In case the delegate represents static method with no target, the instruction
// needs to be able to access the actual arguments to continue with the call so it
// needs to know whether there is an empty stack slot between the delegate ptr and the
// rest of the args
gboolean first_arg_is_simd = td->locals [sp_args [1].local].flags & INTERP_LOCAL_FLAG_SIMD;
td->last_ins->data [2] = first_arg_is_simd ? MINT_SIMD_ALIGNMENT : MINT_STACK_SLOT_SIZE;
}
} else if (calli) {
MintICallSig icall_sig = MINT_ICALLSIG_MAX;
#ifndef MONO_ARCH_HAS_NO_PROPER_MONOCTX
Expand Down

0 comments on commit 49f9f7a

Please sign in to comment.