From: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Sep 2021 16:52:00 +0000 (-0700) Subject: [release/6.0] [mini] Use alloca for runtime_invoke retval buffer (#59006) X-Git-Tag: accepted/tizen/unified/20220110.054933~163 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8fe648d65ff5e04cbd503ed847f2705800e84e68;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [release/6.0] [mini] Use alloca for runtime_invoke retval buffer (#59006) * [mini] Use alloca for runtime_invoke retval buffer Fixes https://github.com/dotnet/runtime/issues/58957 Related to https://github.com/dotnet/runtime/pull/58215 which was attempting to fix https://github.com/dotnet/runtime/issues/58190 * Set initial return buffer size to TARGET_SIZEOF_VOID_P In the common case we use the return buffer just to hold a pointer to the return value Co-authored-by: Aleksey Kliger Co-authored-by: Aleksey Kliger --- diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 2abfe01..f3c9c9b 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -2999,7 +2999,7 @@ typedef struct { gpointer *wrapper_arg; } RuntimeInvokeInfo; -#define MONO_SIZEOF_DYN_CALL_RET_BUF 256 +#define MONO_SIZEOF_DYN_CALL_RET_BUF TARGET_SIZEOF_VOID_P static RuntimeInvokeInfo* create_runtime_invoke_info (MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt, gboolean use_interp, MonoError *error) @@ -3159,9 +3159,8 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void { MonoMethodSignature *sig = info->sig; MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method); - gboolean retval_malloc = FALSE; - gpointer retval_ptr; - guint8 retval [MONO_SIZEOF_DYN_CALL_RET_BUF]; + int32_t retval_size = MONO_SIZEOF_DYN_CALL_RET_BUF; + gpointer retval = NULL; int i, pindex; error_init (error); @@ -3191,19 +3190,18 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void if (info->ret_box_class && !sig->ret->byref && (sig->ret->type == MONO_TYPE_VALUETYPE || (sig->ret->type == MONO_TYPE_GENERICINST && !MONO_TYPE_IS_REFERENCE (sig->ret)))) { - // if the return type is a struct and its too big for the stack buffer, malloc instead + // if the return type is a struct, allocate enough stack space to hold it MonoClass *ret_klass = mono_class_from_mono_type_internal (sig->ret); g_assert (!mono_class_has_failure (ret_klass)); int32_t inst_size = mono_class_instance_size (ret_klass); if (inst_size > MONO_SIZEOF_DYN_CALL_RET_BUF) { - retval_malloc = TRUE; - retval_ptr = g_new0 (guint8, inst_size); - g_assert (retval_ptr); + retval_size = inst_size; } } - if (!retval_malloc) - retval_ptr = &retval; - args [pindex ++] = &retval_ptr; + } + retval = g_alloca (retval_size); + if (sig->ret->type != MONO_TYPE_VOID) { + args [pindex ++] = &retval; } for (i = 0; i < sig->param_count; ++i) { MonoType *t = sig->params [i]; @@ -3252,9 +3250,7 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void if (sig->ret->byref) { return mono_value_box_checked (info->ret_box_class, *(gpointer*)retval, error); } else { - MonoObject *ret = mono_value_box_checked (info->ret_box_class, retval_ptr, error); - if (retval_malloc) - g_free (retval_ptr); + MonoObject *ret = mono_value_box_checked (info->ret_box_class, retval, error); return ret; } } else { @@ -3418,25 +3414,22 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec gpointer *args; int i, pindex, buf_size; guint8 *buf; - guint8 retbuf [MONO_SIZEOF_DYN_CALL_RET_BUF]; - guint8 *retval = &retbuf[0]; - gboolean retval_malloc = FALSE; + int32_t retval_size = MONO_SIZEOF_DYN_CALL_RET_BUF; + guint8 *retval = NULL; - /* if the return value is too big, put it in a dynamically allocated temporary */ + /* if the return type is a struct and it's too big, allocate more space for it */ if (info->ret_box_class && !sig->ret->byref && (sig->ret->type == MONO_TYPE_VALUETYPE || (sig->ret->type == MONO_TYPE_GENERICINST && !MONO_TYPE_IS_REFERENCE (sig->ret)))) { - // if the return type is a struct and its too big for the stack buffer, malloc instead MonoClass *ret_klass = mono_class_from_mono_type_internal (sig->ret); g_assert (!mono_class_has_failure (ret_klass)); int32_t inst_size = mono_class_instance_size (ret_klass); if (inst_size > MONO_SIZEOF_DYN_CALL_RET_BUF) { - retval_malloc = TRUE; - retval = g_new0 (guint8, inst_size); - g_assert (retval); + retval_size = inst_size; } } + retval = g_alloca (retval_size); /* Convert the arguments to the format expected by start_dyn_call () */ args = (void **)g_alloca ((sig->param_count + sig->hasthis) * sizeof (gpointer)); @@ -3487,8 +3480,6 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec return mono_value_box_checked (info->ret_box_class, *(gpointer*)retval, error); } else { MonoObject *boxed_ret = mono_value_box_checked (info->ret_box_class, retval, error); - if (retval_malloc) - g_free (retval); return boxed_ret; } } else {