Merge pull request #1804 from esdrubal/processmodule
[mono.git] / mono / mini / mini-amd64.c
index c1332ec3bc0272180edf7a4c8934975d356fcc98..744b42be16f8e8ebc3785dc684a64d5a2f980376 100644 (file)
@@ -7851,6 +7851,39 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod
        return start;
 }
 
+#define MAX_VIRTUAL_DELEGATE_OFFSET 32
+
+static gpointer
+get_delegate_virtual_invoke_impl (gboolean load_imt_reg, int offset, guint32 *code_len)
+{
+       guint8 *code, *start;
+       int size = 20;
+
+       if (offset / sizeof (gpointer) > MAX_VIRTUAL_DELEGATE_OFFSET)
+               return NULL;
+
+       start = code = mono_global_codeman_reserve (size);
+
+       /* Replace the this argument with the target */
+       amd64_mov_reg_reg (code, AMD64_RAX, AMD64_ARG_REG1, 8);
+       amd64_mov_reg_membase (code, AMD64_ARG_REG1, AMD64_RAX, MONO_STRUCT_OFFSET (MonoDelegate, target), 8);
+
+       if (load_imt_reg) {
+               /* Load the IMT reg */
+               amd64_mov_reg_membase (code, MONO_ARCH_IMT_REG, AMD64_RAX, MONO_STRUCT_OFFSET (MonoDelegate, method), 8);
+       }
+
+       /* Load the vtable */
+       amd64_mov_reg_membase (code, AMD64_RAX, AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoObject, vtable), 8);
+       amd64_jump_membase (code, AMD64_RAX, offset);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+
+       if (code_len)
+               *code_len = code - start;
+
+       return start;
+}
+
 /*
  * mono_arch_get_delegate_invoke_impls:
  *
@@ -7876,6 +7909,18 @@ mono_arch_get_delegate_invoke_impls (void)
                g_free (tramp_name);
        }
 
+       for (i = 0; i < MAX_VIRTUAL_DELEGATE_OFFSET; ++i) {
+               code = get_delegate_virtual_invoke_impl (TRUE, i * SIZEOF_VOID_P, &code_len);
+               tramp_name = g_strdup_printf ("delegate_virtual_invoke_imt_%d", i);
+               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
+               g_free (tramp_name);
+
+               code = get_delegate_virtual_invoke_impl (FALSE, i * SIZEOF_VOID_P, &code_len);
+               tramp_name = g_strdup_printf ("delegate_virtual_invoke_%d", i);
+               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
+               g_free (tramp_name);
+       }
+
        return res;
 }
 
@@ -7937,26 +7982,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
 gpointer
 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg)
 {
-       guint8 *code, *start;
-       int size = 20;
-
-       start = code = mono_global_codeman_reserve (size);
-
-       /* Replace the this argument with the target */
-       amd64_mov_reg_reg (code, AMD64_RAX, AMD64_ARG_REG1, 8);
-       amd64_mov_reg_membase (code, AMD64_ARG_REG1, AMD64_RAX, MONO_STRUCT_OFFSET (MonoDelegate, target), 8);
-
-       if (load_imt_reg) {
-               /* Load the IMT reg */
-               amd64_mov_reg_membase (code, MONO_ARCH_IMT_REG, AMD64_RAX, MONO_STRUCT_OFFSET (MonoDelegate, method), 8);
-       }
-
-       /* Load the vtable */
-       amd64_mov_reg_membase (code, AMD64_RAX, AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoObject, vtable), 8);
-       amd64_jump_membase (code, AMD64_RAX, offset);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
-
-       return start;
+       return get_delegate_virtual_invoke_impl (load_imt_reg, offset, NULL);
 }
 
 void