Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mono][interp] Fix calling of static delegates with simd arguments #92927

Merged
merged 3 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -3996,9 +3996,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 @@ -4044,6 +4041,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 @@ -4062,10 +4060,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
Loading