From cd79652e8e32b069e40e56716464ac72e002af51 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Tue, 3 Sep 2019 11:21:56 +0300 Subject: [PATCH] [interp] Remove varargs from InterpFrame and recompute it instead (mono/mono#16598) It is a waste of stack space. Commit migrated from https://github.com/mono/mono/commit/f491af13f482fb42313aa5919ef6e2a030501994 --- src/mono/mono/mini/interp/interp-internals.h | 1 - src/mono/mono/mini/interp/interp.c | 19 +++++++++++++------ src/mono/mono/mini/interp/transform.c | 4 +++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/mono/mono/mini/interp/interp-internals.h b/src/mono/mono/mini/interp/interp-internals.h index 3dcb0de..f359f1c 100644 --- a/src/mono/mono/mini/interp/interp-internals.h +++ b/src/mono/mono/mini/interp/interp-internals.h @@ -131,7 +131,6 @@ struct _InterpFrame { InterpFrame *parent; /* parent */ InterpMethod *imethod; /* parent */ stackval *retval; /* parent */ - char *varargs; stackval *stack_args; /* parent */ stackval *stack; /* diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 066f34d..be74296 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -2355,14 +2355,16 @@ do_transform_method (InterpFrame *frame, ThreadContext *context) } static MONO_NEVER_INLINE guchar* -copy_varargs_vtstack (MonoMethodSignature *csig, stackval *sp, guchar *vt_sp) +copy_varargs_vtstack (MonoMethodSignature *csig, stackval *sp, guchar *vt_sp_start) { stackval *first_arg = sp - csig->param_count; + guchar *vt_sp = vt_sp_start; /* * We need to have the varargs linearly on the stack so the ArgIterator * can iterate over them. We pass the signature first and then copy them - * one by one on the vtstack. + * one by one on the vtstack. At the end we pass the original vt_stack + * so the callee (MINT_ARGLIST) can find the varargs space. */ *(gpointer*)vt_sp = csig; vt_sp += sizeof (gpointer); @@ -2376,7 +2378,12 @@ copy_varargs_vtstack (MonoMethodSignature *csig, stackval *sp, guchar *vt_sp) vt_sp += arg_size; } - return (guchar*)ALIGN_PTR_TO (vt_sp, MINT_VT_ALIGNMENT); + vt_sp += sizeof (gpointer); + vt_sp = (guchar*)ALIGN_PTR_TO (vt_sp, MINT_VT_ALIGNMENT); + + ((gpointer*)vt_sp) [-1] = vt_sp_start; + + return vt_sp; } /* @@ -3243,6 +3250,8 @@ mono_interp_store_remote_field_vt (InterpFrame* frame, const guint16* ip, stackv * If BASE_FRAME is not NULL, copy arguments/locals from BASE_FRAME. * The ERROR argument is used to avoid declaring an error object for every interp frame, its not used * to return error information. + * + * Currently this method uses 0x88 of stack space on 64bit gcc. Make sure to keep it under control. */ static void interp_exec_method_full (InterpFrame *frame, ThreadContext *context, FrameClauseArgs *clause_args, MonoError *error) @@ -3341,9 +3350,8 @@ main_loop: ++sp; MINT_IN_BREAK; MINT_IN_CASE(MINT_ARGLIST) - g_assert (frame->varargs); sp->data.p = vt_sp; - *(gpointer*)sp->data.p = frame->varargs; + *(gpointer*)sp->data.p = ((gpointer*)frame->retval->data.p) [-1]; vt_sp += ALIGN_TO (sizeof (gpointer), MINT_VT_ALIGNMENT); ++ip; ++sp; @@ -3630,7 +3638,6 @@ main_loop: csig = (MonoMethodSignature*) frame->imethod->data_items [* (guint16*) (ip + 2)]; /* Push all vararg arguments from normal sp to vt_sp together with the signature */ num_varargs = csig->param_count - csig->sentinelpos; - child_frame.varargs = (char*) vt_sp; vt_sp = copy_varargs_vtstack (csig, sp, vt_sp); ip += 3; diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 1451915..b735705 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -2070,8 +2070,10 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target for (i = csignature->sentinelpos; i < csignature->param_count; ++i) { int align, arg_size; arg_size = mono_type_stack_size (csignature->params [i], &align); - vararg_stack += arg_size; + vararg_stack += ALIGN_TO (arg_size, align); } + /* allocate space for the pointer to varargs space start */ + vararg_stack += sizeof (gpointer); vt_stack_used += ALIGN_TO (vararg_stack, MINT_VT_ALIGNMENT); PUSH_VT (td, vararg_stack); } -- 2.7.4