[Mono-patches] r78326 - trunk/mono/mono/mini
Zoltan Varga (vargaz AT gmail.com)
mono-patches-list at lists.ximian.com
Thu May 31 09:43:49 EDT 2007
Author: zoltan
Date: 2007-05-31 09:43:48 -0400 (Thu, 31 May 2007)
New Revision: 78326
Modified:
trunk/mono/mono/mini/ChangeLog
trunk/mono/mono/mini/inssel.brg
trunk/mono/mono/mini/mini-amd64.c
trunk/mono/mono/mini/mini-ia64.h
trunk/mono/mono/mini/mini-trampolines.c
trunk/mono/mono/mini/mini-x86.h
trunk/mono/mono/mini/mini.c
trunk/mono/mono/mini/mini.h
trunk/mono/mono/mini/tramp-amd64.c
Log:
2007-05-31 Zoltan Varga <vargaz at gmail.com>
* inssel.brg (mini_emit_virtual_call): Call delegate->Invoke through the delegate's
invoke_impl field.
* mini-amd64.c (mono_arch_get_delegate_invoke_impl): New arch dependent function.
(mono_arch_get_this_arg_from_call): Ditto.
* tramp-amd64.c (mono_arch_patch_delegate_trampoline): Removed.
* mini-trampolines.c (mono_delegate_trampoline): Complete rewrite. On first call,
try to create optimized invoke code and use that for further invocations.
Otherwise, use the original mono_marshal_get_delegate_invoke () implementation.
* mini-x86.h mini-ia64.h: Remove MONO_ARCH_HAS_CREATE_DELEGATE_TRAMPOLINE for now.
Modified: trunk/mono/mono/mini/ChangeLog
===================================================================
--- trunk/mono/mono/mini/ChangeLog 2007-05-31 13:43:40 UTC (rev 78325)
+++ trunk/mono/mono/mini/ChangeLog 2007-05-31 13:43:48 UTC (rev 78326)
@@ -1,3 +1,19 @@
+2007-05-31 Zoltan Varga <vargaz at gmail.com>
+
+ * inssel.brg (mini_emit_virtual_call): Call delegate->Invoke through the delegate's
+ invoke_impl field.
+
+ * mini-amd64.c (mono_arch_get_delegate_invoke_impl): New arch dependent function.
+ (mono_arch_get_this_arg_from_call): Ditto.
+
+ * tramp-amd64.c (mono_arch_patch_delegate_trampoline): Removed.
+
+ * mini-trampolines.c (mono_delegate_trampoline): Complete rewrite. On first call,
+ try to create optimized invoke code and use that for further invocations.
+ Otherwise, use the original mono_marshal_get_delegate_invoke () implementation.
+
+ * mini-x86.h mini-ia64.h: Remove MONO_ARCH_HAS_CREATE_DELEGATE_TRAMPOLINE for now.
+
2007-05-29 Rodrigo Kumpera <kumpera at gmail.com>
* inssel.brg (mini_emit_virtual_call): Statically dispatch virtual calls to
Modified: trunk/mono/mono/mini/inssel.brg
===================================================================
--- trunk/mono/mono/mini/inssel.brg 2007-05-31 13:43:40 UTC (rev 78325)
+++ trunk/mono/mono/mini/inssel.brg 2007-05-31 13:43:48 UTC (rev 78326)
@@ -1698,6 +1698,16 @@
mono_bblock_add_inst (cfg->cbb, tree);
return;
}
+
+ if ((method->klass->parent == mono_defaults.multicastdelegate_class) && (!strcmp (method->name, "Invoke"))) {
+ /* Make a call to delegate->invoke_impl */
+ tree->dreg = state->reg1;
+ tree->opcode = virtop;
+ tree->inst_basereg = this_reg;
+ tree->inst_offset = G_STRUCT_OFFSET (MonoDelegate, invoke_impl);
+ mono_bblock_add_inst (cfg->cbb, tree);
+ return;
+ }
if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) &&
((method->flags & METHOD_ATTRIBUTE_FINAL) ||
Modified: trunk/mono/mono/mini/mini-amd64.c
===================================================================
--- trunk/mono/mono/mini/mini-amd64.c 2007-05-31 13:43:40 UTC (rev 78325)
+++ trunk/mono/mono/mini/mini-amd64.c 2007-05-31 13:43:48 UTC (rev 78326)
@@ -5199,26 +5199,62 @@
return (gpointer)(((guint64)(regs [reg])) + disp);
}
-gpointer*
-mono_arch_get_delegate_method_ptr_addr (guint8* code, gpointer *regs)
+gpointer
+mono_arch_get_this_arg_from_call (MonoMethodSignature *sig, gssize *regs, guint8 *code)
{
- guint32 reg;
- guint32 disp;
+ if (MONO_TYPE_ISSTRUCT (sig->ret))
+ return (gpointer)regs [AMD64_RSI];
+ else
+ return (gpointer)regs [AMD64_RDI];
+}
- code -= 10;
+gpointer
+mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
+{
+ guint8 *code, *start;
+ MonoDomain *domain = mono_domain_get ();
+ int i;
- if (IS_REX (code [0]) && (code [1] == 0x8b) && (code [3] == 0x48) && (code [4] == 0x8b) && (code [5] == 0x40) && (code [7] == 0x48) && (code [8] == 0xff) && (code [9] == 0xd0)) {
- /* mov REG, %rax; mov <OFFSET>(%rax), %rax; call *%rax */
- reg = amd64_rex_b (code [0]) + amd64_modrm_rm (code [2]);
- disp = code [6];
+ /* FIXME: Support more cases */
+ if (MONO_TYPE_ISSTRUCT (sig->ret))
+ return NULL;
- if (reg == AMD64_RAX)
+ if (has_target) {
+ mono_domain_lock (domain);
+ start = code = mono_code_manager_reserve (domain->code_mp, 64);
+ mono_domain_unlock (domain);
+
+ /* Replace the this argument with the target */
+ amd64_mov_reg_reg (code, AMD64_RAX, AMD64_RDI, 8);
+ amd64_mov_reg_membase (code, AMD64_RDI, AMD64_RAX, G_STRUCT_OFFSET (MonoDelegate, target), 8);
+ amd64_jump_membase (code, AMD64_RAX, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
+
+ g_assert ((code - start) < 64);
+ } else {
+ for (i = 0; i < sig->param_count; ++i)
+ if (!mono_is_regsize_var (sig->params [i]))
+ return NULL;
+ if (sig->param_count > 4)
return NULL;
- else
- return (gpointer*)(((guint64)(regs [reg])) + disp);
+
+ mono_domain_lock (domain);
+ start = code = mono_code_manager_reserve (domain->code_mp, 64);
+ mono_domain_unlock (domain);
+
+ if (sig->param_count == 0) {
+ amd64_jump_membase (code, AMD64_RDI, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
+ } else {
+ /* We have to shift the arguments left */
+ amd64_mov_reg_reg (code, AMD64_RAX, AMD64_RDI, 8);
+ for (i = 0; i < sig->param_count; ++i)
+ amd64_mov_reg_reg (code, param_regs [i], param_regs [i + 1], 8);
+
+ amd64_jump_membase (code, AMD64_RAX, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
+ }
+ g_assert ((code - start) < 64);
}
- return NULL;
+ return start;
}
/*
Modified: trunk/mono/mono/mini/mini-ia64.h
===================================================================
--- trunk/mono/mono/mini/mini-ia64.h 2007-05-31 13:43:40 UTC (rev 78325)
+++ trunk/mono/mono/mini/mini-ia64.h 2007-05-31 13:43:48 UTC (rev 78326)
@@ -181,7 +181,6 @@
#define MONO_ARCH_HAVE_PIC_AOT 1
#define MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN 1
#define MONO_ARCH_HAVE_CREATE_SPECIFIC_TRAMPOLINE 1
-#define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
#define MONO_ARCH_HAVE_SAVE_UNWIND_INFO 1
#define MONO_ARCH_HAVE_CREATE_VARS 1
Modified: trunk/mono/mono/mini/mini-trampolines.c
===================================================================
--- trunk/mono/mono/mini/mini-trampolines.c 2007-05-31 13:43:40 UTC (rev 78325)
+++ trunk/mono/mono/mini/mini-trampolines.c 2007-05-31 13:43:48 UTC (rev 78326)
@@ -178,20 +178,75 @@
/**
* mono_delegate_trampoline:
*
- * This trampoline handles calls made from the delegate invoke wrapper. It patches
- * the function address inside the delegate.
+ * This trampoline handles calls made to Delegate:Invoke ().
*/
gpointer
-mono_delegate_trampoline (gssize *regs, guint8 *code, MonoMethod *m, guint8* tramp)
+mono_delegate_trampoline (gssize *regs, guint8 *code, MonoClass *klass, guint8* tramp)
{
- gpointer addr;
+ MonoDomain *domain = mono_domain_get ();
+ MonoDelegate *delegate;
+ MonoJitInfo *ji;
+ gpointer iter;
+ MonoMethod *invoke;
+ gboolean multicast;
- addr = mono_compile_method (m);
- g_assert (addr);
+ /* Find the Invoke method */
+ iter = NULL;
+ while ((invoke = mono_class_get_methods (klass, &iter))) {
+ if (!strcmp (invoke->name, "Invoke"))
+ break;
+ }
+ g_assert (invoke);
- mono_arch_patch_delegate_trampoline (code, tramp, regs, addr);
+ /* Obtain the delegate object according to the calling convention */
- return addr;
+ delegate = mono_arch_get_this_arg_from_call (mono_method_signature (invoke), regs, code);
+
+ /*
+ * If the called address is a trampoline, replace it with the compiled method so
+ * further calls don't have to go through the trampoline.
+ */
+ ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (delegate->method_ptr));
+ if (ji)
+ delegate->method_ptr = mono_compile_method (ji->method);
+
+ multicast = ((MonoMulticastDelegate*)delegate)->prev != NULL;
+ if (!multicast) {
+ guint8* code;
+ GHashTable *cache;
+
+ mono_domain_lock (domain);
+ if (delegate->target != NULL) {
+ if (!domain->delegate_invoke_impl_with_target_hash)
+ domain->delegate_invoke_impl_with_target_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+ cache = domain->delegate_invoke_impl_with_target_hash;
+ } else {
+ if (!domain->delegate_invoke_impl_no_target_hash)
+ domain->delegate_invoke_impl_no_target_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+ cache = domain->delegate_invoke_impl_no_target_hash;
+ }
+ code = g_hash_table_lookup (cache, mono_method_signature (invoke));
+ mono_domain_unlock (domain);
+ if (code) {
+ delegate->invoke_impl = code;
+ return code;
+ }
+
+ code = mono_arch_get_delegate_invoke_impl (mono_method_signature (invoke), delegate->target != NULL);
+
+ if (code) {
+ mono_domain_lock (domain);
+ g_hash_table_insert (cache, mono_method_signature (invoke), code);
+ mono_domain_unlock (domain);
+
+ delegate->invoke_impl = code;
+ return code;
+ }
+ }
+
+ /* The general, unoptimized case */
+ delegate->invoke_impl = mono_compile_method (mono_marshal_get_delegate_invoke (invoke));
+ return delegate->invoke_impl;
}
#endif
Modified: trunk/mono/mono/mini/mini-x86.h
===================================================================
--- trunk/mono/mono/mini/mini-x86.h 2007-05-31 13:43:40 UTC (rev 78325)
+++ trunk/mono/mono/mini/mini-x86.h 2007-05-31 13:43:48 UTC (rev 78326)
@@ -250,7 +250,6 @@
#define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
#define MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN 1
#define MONO_ARCH_HAVE_CREATE_SPECIFIC_TRAMPOLINE 1
-#define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
#define MONO_ARCH_HAVE_CREATE_VARS 1
#endif /* __MONO_MINI_X86_H__ */
Modified: trunk/mono/mono/mini/mini.c
===================================================================
--- trunk/mono/mono/mini/mini.c 2007-05-31 13:43:40 UTC (rev 78325)
+++ trunk/mono/mono/mini/mini.c 2007-05-31 13:43:48 UTC (rev 78326)
@@ -8124,43 +8124,32 @@
#endif
static gpointer
-mono_create_delegate_trampoline (MonoMethod *method, gpointer addr)
+mono_create_delegate_trampoline (MonoClass *klass)
{
#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
+ MonoDomain *domain = mono_domain_get ();
gpointer code, ptr;
guint32 code_size;
- MonoDomain *domain = mono_domain_get ();
-#ifndef __ia64__
- code = mono_jit_find_compiled_method (domain, method);
- if (code)
- return code;
-#else
- /*
- * FIXME: We should return a function descriptor here but it is not stored
- * anywhere so it would be leaked.
- */
-#endif
-
mono_domain_lock (domain);
- ptr = g_hash_table_lookup (domain->delegate_trampoline_hash, method);
+ ptr = g_hash_table_lookup (domain->delegate_trampoline_hash, klass);
mono_domain_unlock (domain);
if (ptr)
return ptr;
- code = mono_arch_create_specific_trampoline (method, MONO_TRAMPOLINE_DELEGATE, domain, &code_size);
+ code = mono_arch_create_specific_trampoline (klass, MONO_TRAMPOLINE_DELEGATE, mono_domain_get (), &code_size);
ptr = mono_create_ftnptr (domain, code);
/* store trampoline address */
mono_domain_lock (domain);
g_hash_table_insert (domain->delegate_trampoline_hash,
- method, ptr);
+ klass, ptr);
mono_domain_unlock (domain);
return ptr;
#else
- return addr;
+ return NULL;
#endif
}
Modified: trunk/mono/mono/mini/mini.h
===================================================================
--- trunk/mono/mono/mini/mini.h 2007-05-31 13:43:40 UTC (rev 78325)
+++ trunk/mono/mono/mini/mini.h 2007-05-31 13:43:48 UTC (rev 78326)
@@ -916,7 +916,7 @@
gpointer mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token) MONO_INTERNAL;
MonoVTable* mono_find_class_init_trampoline_by_addr (gconstpointer addr) MONO_INTERNAL;
gpointer mono_magic_trampoline (gssize *regs, guint8 *code, MonoMethod *m, guint8* tramp) MONO_INTERNAL;
-gpointer mono_delegate_trampoline (gssize *regs, guint8 *code, MonoMethod *m, guint8* tramp) MONO_INTERNAL;
+gpointer mono_delegate_trampoline (gssize *regs, guint8 *code, MonoClass *klass, guint8* tramp) MONO_INTERNAL;
gpointer mono_aot_trampoline (gssize *regs, guint8 *code, guint8 *token_info,
guint8* tramp) MONO_INTERNAL;
gpointer mono_aot_plt_trampoline (gssize *regs, guint8 *code, guint8 *token_info,
@@ -1008,6 +1008,8 @@
void mono_arch_nullify_class_init_trampoline(guint8 *code, gssize *regs) MONO_INTERNAL;
void mono_arch_nullify_plt_entry (guint8 *code) MONO_INTERNAL;
void mono_arch_patch_delegate_trampoline (guint8 *code, guint8 *tramp, gssize *regs, guint8 *addr) MONO_INTERNAL;
+gpointer mono_arch_get_this_arg_from_call (MonoMethodSignature *sig, gssize *regs, guint8 *code);
+gpointer mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target);
gpointer mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len) MONO_INTERNAL;
/* Exception handling */
Modified: trunk/mono/mono/mini/tramp-amd64.c
===================================================================
--- trunk/mono/mono/mini/tramp-amd64.c 2007-05-31 13:43:40 UTC (rev 78325)
+++ trunk/mono/mono/mini/tramp-amd64.c 2007-05-31 13:43:48 UTC (rev 78326)
@@ -160,38 +160,6 @@
mono_arch_patch_plt_entry (code, nullified_class_init_trampoline);
}
-void
-mono_arch_patch_delegate_trampoline (guint8 *code, guint8 *tramp, gssize *regs, guint8 *addr)
-{
- guint8 rex = 0;
- guint32 reg;
- guint32 disp;
-
- if ((code [-3] == 0xff) && (amd64_modrm_reg (code [-2]) == 0x2) && (amd64_modrm_mod (code [-2]) == 0x1)) {
- /* call *[reg+disp8] */
- if (IS_REX (code [-4]))
- rex = code [-4];
- reg = amd64_modrm_rm (code [-2]);
- disp = *(guint8*)(code - 1);
- //printf ("B: [%%r%d+0x%x]\n", reg, disp);
- }
- else {
- int i;
-
- for (i = -16; i < 0; ++i)
- printf ("%d ", code [i]);
- printf ("\n");
- g_assert_not_reached ();
- }
-
- reg += amd64_rex_b (rex);
-
- /* R11 is clobbered by the trampoline code */
- g_assert (reg != AMD64_R11);
-
- *(gpointer*)(((guint64)(regs [reg])) + disp) = addr;
-}
-
guchar*
mono_arch_create_trampoline_code (MonoTrampolineType tramp_type)
{
More information about the Mono-patches
mailing list