[interp] Fix interp entry for methods with lots of arguments in llvmonly+interp mode...
authormonojenkins <jo.shields+jenkins@xamarin.com>
Wed, 20 May 2020 15:20:06 +0000 (11:20 -0400)
committerGitHub <noreply@github.com>
Wed, 20 May 2020 15:20:06 +0000 (11:20 -0400)
Fixes https://github.com/mono/mono/issues/19801.

<!--
Thank you for your Pull Request!

If you are new to contributing to Mono, please try to do your best at conforming to our coding guidelines http://www.mono-project.com/community/contributing/coding-guidelines/ but don't worry if you get something wrong. One of the project members will help you to get things landed.

Does your pull request fix any of the existing issues? Please use the following format: Fixes #issue-number
-->

Co-authored-by: vargaz <vargaz@users.noreply.github.com>
src/mono/mono/mini/aot-compiler.c
src/mono/mono/mini/interp/interp.c
src/mono/mono/mini/interp/interp.h
src/mono/mono/mini/mini-generic-sharing.c

index 762a5a7..adb9cab 100644 (file)
@@ -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 */
index 6572376..35de785 100644 (file)
@@ -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];
index 40c9e96..198d423 100644 (file)
@@ -14,6 +14,8 @@
 #define INTERP_ICALL_TRAMP_FARGS 4
 #endif
 
+#define MAX_INTERP_ENTRY_ARGS 8
+
 struct _InterpMethodArguments {
        size_t ilen;
        gpointer *iargs;
index 23a7028..7ef020e 100644 (file)
@@ -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;