Skip to content

Commit

Permalink
- Only move unaligned stack usage worth of parameters.
Browse files Browse the repository at this point in the history
This is a simple optimization.

- When moving parameters for tailcall, and having pushed ip,
and adjusting the offset to account for that, split the adjustment
between sp and frame pointer, as frame pointer may or may not be sp.
This fixes mono#11489.
  • Loading branch information
jaykrell committed Dec 14, 2018
1 parent d8faa8e commit b97eca9
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 11 deletions.
27 changes: 16 additions & 11 deletions mono/mini/mini-arm.c
Expand Up @@ -1624,10 +1624,10 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
add_general (&gr, &stack_size, &cinfo->sig_cookie, TRUE);
}

// Alignment causes tailcall to copy extra data unnecessarily.
DEBUG (g_print (" stack size: %d (%d)\n", (stack_size + 15) & ~15, stack_size));
stack_size = ALIGN_TO (stack_size, MONO_ARCH_FRAME_ALIGNMENT);

cinfo->stack_usage = stack_size;
cinfo->unaligned_stack_usage = stack_size;
cinfo->stack_usage = ALIGN_TO (stack_size, MONO_ARCH_FRAME_ALIGNMENT);
return cinfo;
}

Expand Down Expand Up @@ -2652,6 +2652,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)

call->call_info = cinfo;
call->stack_usage = cinfo->stack_usage;
call->unaligned_stack_usage = cinfo->unaligned_stack_usage;
}

static void
Expand Down Expand Up @@ -5001,7 +5002,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
gboolean const tailcall_reg = ins->opcode == OP_TAILCALL_REG;
MonoCallInst *call = (MonoCallInst*)ins;

max_len += call->stack_usage / sizeof (target_mgreg_t) * ins_get_size (OP_TAILCALL_PARAMETER);
max_len += call->unaligned_stack_usage / sizeof (target_mgreg_t) * ins_get_size (OP_TAILCALL_PARAMETER);

if (IS_HARD_FLOAT)
code = emit_float_args (cfg, call, code, &max_len, &offset);
Expand Down Expand Up @@ -5035,13 +5036,15 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
* Need to copy the arguments from the callee argument area to
* the caller argument area, and pop the frame.
*/
if (call->stack_usage) {

if (call->unaligned_stack_usage) {
int i, prev_sp_offset = 0;
int saved_ip_offset = 0;
int saved_ip_offset_sp = 0;
int saved_ip_offset_fp = 0;

if (tailcall_membase || tailcall_reg) {
ARM_PUSH (code, 1 << ARMREG_IP);
saved_ip_offset = 4;
saved_ip_offset_sp = 4;
}

/* Compute size of saved registers restored below */
Expand All @@ -5055,16 +5058,18 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
}

code = emit_big_add (code, ARMREG_IP, cfg->frame_reg, cfg->stack_usage + prev_sp_offset);
if (cfg->frame_reg == ARMREG_SP)
saved_ip_offset_fp = saved_ip_offset_sp;

/* Copy arguments on the stack to our argument area */
// FIXME a fixed size memcpy is desirable here,
// at least for larger values of stack_usage.
for (i = 0; i < call->stack_usage; i += sizeof (target_mgreg_t)) {
ARM_LDR_IMM (code, ARMREG_LR, ARMREG_SP, i + saved_ip_offset);
ARM_STR_IMM (code, ARMREG_LR, ARMREG_IP, i + saved_ip_offset);
for (i = 0; i < call->unaligned_stack_usage; i += sizeof (target_mgreg_t)) {
ARM_LDR_IMM (code, ARMREG_LR, ARMREG_SP, i + saved_ip_offset_sp);
ARM_STR_IMM (code, ARMREG_LR, ARMREG_IP, i + saved_ip_offset_fp);
}

if (saved_ip_offset)
if (saved_ip_offset_sp)
ARM_POP (code, 1 << ARMREG_IP);
}

Expand Down
1 change: 1 addition & 0 deletions mono/mini/mini-arm.h
Expand Up @@ -215,6 +215,7 @@ typedef struct {

struct CallInfo {
int nargs;
guint32 unaligned_stack_usage;
guint32 stack_usage;
/* The index of the vret arg in the argument list for RegTypeStructByAddr */
int vret_arg_index;
Expand Down
1 change: 1 addition & 0 deletions mono/mini/mini.h
Expand Up @@ -740,6 +740,7 @@ struct MonoCallInst {
MonoInst *out_args;
MonoInst *vret_var;
gconstpointer fptr;
guint unaligned_stack_usage;
guint stack_usage;
guint stack_align_amount;
guint is_virtual : 1;
Expand Down

0 comments on commit b97eca9

Please sign in to comment.