diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 762a5a743fc29..adb9cab48538c 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -68,6 +68,7 @@ #include "mini-gc.h" #include "mini-llvm.h" #include "mini-runtime.h" +#include "interp/interp.h" static MonoMethod* try_get_method_nofail (MonoClass *klass, const char *method_name, int param_count, int flags) @@ -8608,7 +8609,7 @@ add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean if (gsharedvt_out && g_hash_table_lookup (acfg->gsharedvt_out_signatures, sig)) add_out = FALSE; - if (!add_in && !add_out) + if (!add_in && !add_out && !interp_in) return; if (mini_is_gsharedvt_variable_signature (sig)) @@ -8637,7 +8638,6 @@ add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean if (interp_in) { wrapper = mini_get_interp_in_wrapper (sig); add_extra_method (acfg, wrapper); - //printf ("X: %s\n", mono_method_full_name (wrapper, 1)); } #endif } @@ -8965,7 +8965,16 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) for (l = cfg->interp_in_signatures; l; l = l->next) { MonoMethodSignature *sig = mono_metadata_signature_dup ((MonoMethodSignature*)l->data); - add_gsharedvt_wrappers (acfg, sig, TRUE, FALSE, FALSE); + /* + * Interpreter methods in llvmonly+interp mode are called using gsharedvt_in wrappers, + * since we already generate those in llvmonly mode. But methods with a large + * number of arguments need special processing (see interp_create_method_pointer_llvmonly), + * which only interp_in wrappers do. + */ + if (sig->param_count > MAX_INTERP_ENTRY_ARGS) + add_gsharedvt_wrappers (acfg, sig, FALSE, FALSE, TRUE); + else + add_gsharedvt_wrappers (acfg, sig, TRUE, FALSE, FALSE); } } else if (mono_aot_mode_is_full (&acfg->aot_opts) && mono_aot_mode_is_interp (&acfg->aot_opts)) { /* The interpreter uses these wrappers to call aot-ed code */ diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 4563f1caab66c..67f5c7e5ce7a7 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -2531,8 +2531,6 @@ copy_varargs_vtstack (MonoMethodSignature *csig, stackval *sp, guchar *vt_sp_sta * this/static * ret/void * 16 arguments -> 64 functions. */ -#define MAX_INTERP_ENTRY_ARGS 8 - #define INTERP_ENTRY_BASE(_method, _this_arg, _res) \ InterpEntryData data; \ (data).rmethod = (_method); \ @@ -2819,8 +2817,14 @@ interp_create_method_pointer_llvmonly (MonoMethod *method, gboolean unbox, MonoE * to use a ftndesc. The caller uses a normal signature, while the * entry functions use a gsharedvt_in signature, so wrap the entry function in * a gsharedvt_in_sig wrapper. + * We use a gsharedvt_in_sig wrapper instead of an interp_in wrapper, because they + * are mostly the same, and they are already generated. The exception is the + * wrappers for methods with more than 8 arguments, those are different. */ - wrapper = mini_get_gsharedvt_in_sig_wrapper (sig); + if (sig->param_count > MAX_INTERP_ENTRY_ARGS) + wrapper = mini_get_interp_in_wrapper (sig); + else + wrapper = mini_get_gsharedvt_in_sig_wrapper (sig); entry_wrapper = mono_jit_compile_method_jit_only (wrapper, error); mono_error_assertf_ok (error, "couldn't compile wrapper \"%s\" for \"%s\"", @@ -2828,8 +2832,7 @@ interp_create_method_pointer_llvmonly (MonoMethod *method, gboolean unbox, MonoE mono_method_get_name_full (method, TRUE, TRUE, MONO_TYPE_NAME_FORMAT_IL)); if (sig->param_count > MAX_INTERP_ENTRY_ARGS) { - g_assert_not_reached (); - //entry_func = (gpointer)interp_entry_general; + entry_func = (gpointer)interp_entry_general; } else if (sig->hasthis) { if (sig->ret->type == MONO_TYPE_VOID) entry_func = entry_funcs_instance [sig->param_count]; diff --git a/src/mono/mono/mini/interp/interp.h b/src/mono/mono/mini/interp/interp.h index 40c9e96829e23..198d423f7f4f5 100644 --- a/src/mono/mono/mini/interp/interp.h +++ b/src/mono/mono/mini/interp/interp.h @@ -14,6 +14,8 @@ #define INTERP_ICALL_TRAMP_FARGS 4 #endif +#define MAX_INTERP_ENTRY_ARGS 8 + struct _InterpMethodArguments { size_t ilen; gpointer *iargs; diff --git a/src/mono/mono/mini/mini-generic-sharing.c b/src/mono/mono/mini/mini-generic-sharing.c index 23a702868a81e..7ef020e8c5548 100644 --- a/src/mono/mono/mini/mini-generic-sharing.c +++ b/src/mono/mono/mini/mini-generic-sharing.c @@ -26,6 +26,7 @@ #include "aot-runtime.h" #include "mini-runtime.h" #include "llvmonly-runtime.h" +#include "interp/interp.h" #define ALLOW_PARTIAL_SHARING TRUE //#define ALLOW_PARTIAL_SHARING FALSE @@ -1711,7 +1712,7 @@ mini_get_interp_in_wrapper (MonoMethodSignature *sig) return res; } - if (sig->param_count > 8) + if (sig->param_count > MAX_INTERP_ENTRY_ARGS) /* Call the generic interpreter entry point, the specialized ones only handle a limited number of arguments */ generic = TRUE;