[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