[Mono-list] [review] delegates are cascading.

Dietmar Maurer dietmar@ximian.com
11 Mar 2002 18:24:10 +0100


--=-dhyjUQnnQ/bhuIJa2RF9
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

replying to myself again ;-)=20

One solutions is to use the MonoJitInfo hack, which enable us to find
the method associated with some (JIT compiled code). We need this
functionality for exceptions anyway. I have attached a patch which
includes my modifications to Daniels patch (ignore the included
GetHashCode hack).

- Dietmar=20

On Mon, 2002-03-11 at 15:41, Dietmar Maurer wrote:=20
> more questions:
>=20
> A delegate contains the MethodInfo for the static Method it invokes. But
> delegates are created by a runtime provided constructor which is called
> with 3 arguments:
>=20
> @this  pointer to the delegate to initialize
> @target target object for non static methods, NULL for static methods
> @addr   pointer to native code of the function
>=20
> So how can I obtain the MethodInfo?=20
>=20
> - Dietmar
>=20
> On Mon, 2002-03-11 at 13:57, Dietmar Maurer wrote:
> > Just some questions:
> >=20
> > - why do we need that method_static field (if we need that info we can
> > check (m_target =3D=3D null))
> >=20
> > - how can I call those delegate constructors? All examples I have call
> > the runtime provided constructor instead.
> >=20
> > - Dietmar
> >=20
> >=20
> > On Sat, 2002-03-09 at 10:55, Daniel Stodden wrote:
> > >=20
> > > yay.
> > >=20
> > > attached two lengthy patches over mono/ and mcs/
> > > to make MuticastDelegate::Invoke() run smoothly over combined
> > > delegates. Remove() is missing but I'll finish that over the next day=
s.
> > >=20
> > > i'm pretty certain it is solid, but since it changes quite=20
> > > bit in emit-x86..
> > > please, if someone review this and tell me whether its okay to check =
in.
> > >=20
> > > regards,
> > > dns
> > >=20
> > > abstract: this removes the array-based approach in favour of a revers=
e,
> > > self-contained linked list. [emit-x86].Invoke() then recurses over th=
e
> > > contained links.
> > > Why reverse? The docs require Remove() to kill any _last_ occurences =
of
> > > a combination in the current delegate. any other method needs to
> > > traverse the whole list anyways, so reversing should keep remove more
> > > efficient.
> >=20
> >=20
> >=20
> >=20
> > _______________________________________________
> > Mono-list maillist  -  Mono-list@ximian.com
> > http://lists.ximian.com/mailman/listinfo/mono-list
> --=20
> --------------------------------------------------
> Dietmar Maurer        Maurer IT Systeml=F6sungen KEG
>                                 Technischer Leiter
>=20
> Kohlgasse 51/9             Tel:  +43 1 545 449 711
> A - 1050 WIEN              Fax:  +43 1 545 449 722
>                          Mobil: +43 699 105 880 32
> dietmar@maurer-it.com
> http://www.maurer-it.com
> ---------------------------------------------------
>=20
>=20
>=20
> _______________________________________________
> Mono-list maillist  -  Mono-list@ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list
--=20
--------------------------------------------------
Dietmar Maurer        Maurer IT Systeml=F6sungen KEG
                                Technischer Leiter

Kohlgasse 51/9             Tel:  +43 1 545 449 711
A - 1050 WIEN              Fax:  +43 1 545 449 722
                         Mobil: +43 699 105 880 32
dietmar@maurer-it.com
http://www.maurer-it.com
---------------------------------------------------


--=-dhyjUQnnQ/bhuIJa2RF9
Content-Disposition: attachment; filename=mono.diff
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1

Index: interpreter/ChangeLog
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/interpreter/ChangeLog,v
retrieving revision 1.119
diff -u -r1.119 ChangeLog
--- interpreter/ChangeLog	2002/03/11 09:57:42	1.119
+++ interpreter/ChangeLog	2002/03/11 13:28:38
@@ -1,3 +1,6 @@
+2002-03-11  Dietmar Maurer  <dietmar@ximian.com>
+
+	* interp.c (ves_runtime_method): set method_info field
=20
 Mon Mar 11 14:48:07 CET 2002 Paolo Molaro <lupus@ximian.com>
=20
Index: interpreter/interp.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/interpreter/interp.c,v
retrieving revision 1.148
diff -u -r1.148 interp.c
--- interpreter/interp.c	2002/03/11 09:57:42	1.148
+++ interpreter/interp.c	2002/03/11 13:28:38
@@ -536,17 +536,21 @@
 	MonoDelegate *delegate =3D (MonoDelegate*)frame->obj;
 	MonoInvocation call;
=20
-	mono_class_init (mono_defaults.delegate_class);
+	mono_class_init (mono_defaults.multicastdelegate_class);
 =09
 	if (*name =3D=3D '.' && (strcmp (name, ".ctor") =3D=3D 0) && obj &&
-			mono_object_isinst (obj, mono_defaults.delegate_class)) {
+			mono_object_isinst (obj, mono_defaults.multicastdelegate_class)) {
 		delegate->target =3D frame->stack_args[0].data.p;
 		delegate->method_ptr =3D frame->stack_args[1].data.p;
+		if (!delegate->target) {
+			MonoDomain *domain =3D mono_domain_get ();
+			MonoMethod *m =3D mono_method_pointer_get (delegate->method_ptr);
+			delegate->method_info =3D mono_method_get_object (domain, m);
+		}
 		return;
 	}
 	if (*name =3D=3D 'I' && (strcmp (name, "Invoke") =3D=3D 0) && obj &&
-			mono_object_isinst (obj, mono_defaults.delegate_class)) {
-		MonoPIFunc func;
+			mono_object_isinst (obj, mono_defaults.multicastdelegate_class)) {
 		guchar *code;
 		MonoMethod *method;
 	=09
@@ -3702,7 +3706,7 @@
 		g_snprintf (buf, sizeof (buf), "%s.%s::%s(%d)",
 			p->u.method->klass->name_space, p->u.method->klass->name,
 			p->u.method->name, p->u.method->signature->param_count);
-		printf ("%-52s %7d %7ld %7d\n", buf,
+		printf ("%-52s %7d %7llu %7d\n", buf,
 			(gint)(p->total*1000), p->count, (gint)((p->total*1000)/p->count));
 	}
 }
Index: jit/ChangeLog
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/jit/ChangeLog,v
retrieving revision 1.125
diff -u -r1.125 ChangeLog
--- jit/ChangeLog	2002/03/11 09:58:01	1.125
+++ jit/ChangeLog	2002/03/11 13:28:39
@@ -1,4 +1,9 @@
+2002-03-11  Dietmar Maurer  <dietmar@ximian.com>
=20
+	* emit-x86.c (mono_delegate_ctor): use C impl. instead of x86_*
+	macros, included new delegate code from Daniel Stodden.=20
+=09
+=09
 Mon Mar 11 14:47:21 CET 2002 Paolo Molaro <lupus@ximian.com>
=20
 	* jit.c: verify that corlib and runtime are in sync.
Index: jit/emit-x86.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/jit/emit-x86.c,v
retrieving revision 1.63
diff -u -r1.63 emit-x86.c
--- jit/emit-x86.c	2002/03/11 06:41:08	1.63
+++ jit/emit-x86.c	2002/03/11 13:28:39
@@ -876,6 +876,26 @@
 	return 0;
 }
=20
+static void
+mono_delegate_ctor (MonoDelegate *this, MonoObject *target, gpointer addr)
+{
+	MonoDomain *domain =3D mono_domain_get ();
+	MonoClass *class;
+	MonoJitInfo *ji;
+
+	g_assert (this);
+	g_assert (addr);
+
+	class =3D this->object.vtable->klass;
+
+	if (!target && (ji =3D mono_jit_info_table_find (mono_jit_info_table, add=
r)))
+		this->method_info =3D mono_method_get_object (domain, ji->method);
+=09
+	this->target =3D target;
+	this->method_ptr =3D addr;
+
+}
+
 /**
  * arch_compile_method:
  * @method: pointer to the method info
@@ -916,51 +936,36 @@
 	}
=20
 	if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
-		MonoClassField *field;
 		const char *name =3D method->name;
-		static guint target_offset =3D 0;
-		static guint method_offset =3D 0;
+		static guint prev_offset =3D 0;
+
 		guint8 *code;
 		gboolean delegate =3D FALSE;
=20
-		if (method->klass->parent &&=20
-		    method->klass->parent->parent =3D=3D mono_defaults.delegate_class)
+		if (method->klass->parent =3D=3D mono_defaults.multicastdelegate_class)
 			delegate =3D TRUE;
 			=09
-		if (!target_offset) {
-			mono_class_init (mono_defaults.delegate_class);
-
-			field =3D mono_class_get_field_from_name (mono_defaults.delegate_class,=
 "m_target");
-			target_offset =3D field->offset;
-			field =3D mono_class_get_field_from_name (mono_defaults.delegate_class,=
 "method_ptr");
-			method_offset =3D field->offset;
+		if (!prev_offset) {
+			MonoClassField *field;
+			mono_class_init (mono_defaults.multicastdelegate_class);
+			field =3D mono_class_get_field_from_name (mono_defaults.multicastdelega=
te_class, "prev");
+			g_assert (field);
+			prev_offset =3D field->offset;
 		}
 	=09
 		if (delegate && *name =3D=3D '.' && (strcmp (name, ".ctor") =3D=3D 0)) {
-			addr =3D code =3D g_malloc (32);
-			x86_push_reg (code, X86_EBP);
-			x86_mov_reg_reg (code, X86_EBP, X86_ESP, 4);
-		=09
-			/* load the this pointer */
-			x86_mov_reg_membase (code, X86_EAX, X86_EBP, 8, 4);=20
-			/* load m_target arg */
-			x86_mov_reg_membase (code, X86_EDX, X86_EBP, 12, 4);
-			/* store mtarget */
-			x86_mov_membase_reg (code, X86_EAX, target_offset, X86_EDX, 4);=20
-			/* load method_ptr arg */
-			x86_mov_reg_membase (code, X86_EDX, X86_EBP, 16, 4);
-			/* store method_ptr */
-			x86_mov_membase_reg (code, X86_EAX, method_offset, X86_EDX, 4);=20
-
-			x86_leave (code);
-			x86_ret (code);
-
-			g_assert ((code - (guint8*)addr) < 32);
-
+			addr =3D mono_delegate_ctor;
 		} else if (delegate && *name =3D=3D 'I' && (strcmp (name, "Invoke") =3D=
=3D 0)) {
+			/*
+			 *	Invoke( args .. ) {
+			 *		if ( prev )
+			 *			prev.Invoke();
+			 *		return this.<m_target>( args );
+			 *	}
+			 */
 			MonoMethodSignature *csig =3D method->signature;
-			int i, arg_size, target, this_pos =3D 4;
-			guint8 *source;
+			guint8 *br[2], *pos[2];
+			int i, arg_size, this_pos =3D 4;
 		=09
 			if (csig->ret->type =3D=3D MONO_TYPE_VALUETYPE) {
 				g_assert (!csig->ret->byref);
@@ -979,50 +984,89 @@
=20
 			addr =3D g_malloc (64 + arg_size);
=20
-			for (i =3D 0; i < 2; i ++) {
-				int j;
+			code =3D addr;
+			/* load the this pointer */
+			x86_mov_reg_membase (code, X86_EAX, X86_ESP, this_pos, 4);
+		=09
+			/* load prev */
+			x86_mov_reg_membase (code, X86_EDX, X86_EAX, prev_offset, 4);
=20
-				code =3D addr;
-				/* load the this pointer */
-				x86_mov_reg_membase (code, X86_EAX, X86_ESP, this_pos, 4);
-				/* load mtarget */
-				x86_mov_reg_membase (code, X86_EDX, X86_EAX, target_offset, 4);=20
-				/* check if zero (static method call without this pointer) */
-				x86_alu_reg_imm (code, X86_CMP, X86_EDX, 0);
-				x86_branch32 (code, X86_CC_EQ, target, TRUE);=20
-				source =3D code;
-
-				/* virtual delegate methods: we have to replace the this pointer=20
-				 * withe the actual target */
-				x86_mov_membase_reg (code, X86_ESP, this_pos, X86_EDX, 4);=20
-				/* jump to method_ptr() */
-				x86_jump_membase (code, X86_EAX, method_offset);
-
-				/* static delegate methods: we have to remove the this pointer=20
-				 * from the activation frame - I do this do creating a new=20
-				 * stack frame an copy all arguments except the this pointer */
-
-				target =3D code - source;
-				g_assert ((arg_size & 3) =3D=3D 0);
-				for (j =3D 0; j < (arg_size>>2); j++) {
-					x86_push_membase (code, X86_ESP, (arg_size + this_pos));
-				}
+			/* prev =3D=3D 0 ? */
+			x86_alu_reg_imm (code, X86_CMP, X86_EDX, 0);
+			br[0] =3D code; x86_branch32 (code, X86_CC_EQ, 0, TRUE );
+			pos[0] =3D code;
+
+			x86_push_reg( code, X86_EAX );
+			/* push args */
+			for ( i =3D 0; i < (arg_size>>2); i++ )
+				x86_push_membase( code, X86_ESP, (arg_size + this_pos + 4) );
+			/* push next */
+			x86_push_reg( code, X86_EDX );
+			if (this_pos =3D=3D 8)
+				x86_push_membase (code, X86_ESP, (arg_size + 8));
+			/* recurse */
+			br[1] =3D code; x86_call_imm( code, 0 );
+			pos[1] =3D code; x86_call_imm( br[1], addr - pos[1] );
+
+			if (this_pos =3D=3D 8)
+				x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + 8);
+			else
+				x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + 4);
+			x86_pop_reg( code, X86_EAX );
+		=09
+			/* prev =3D=3D 0 */=20
+			x86_branch32( br[0], X86_CC_EQ, code - pos[0], TRUE );
+		=09
+			/* load mtarget */
+			x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (MonoDeleg=
ate, target), 4);=20
+			/* mtarget =3D=3D 0 ? */
+			x86_alu_reg_imm (code, X86_CMP, X86_EDX, 0);
+			br[0] =3D code; x86_branch32 (code, X86_CC_EQ, 0, TRUE);
+			pos[0] =3D code;
+
+			/*=20
+			 * virtual delegate methods: we have to
+			 * replace the this pointer with the actual
+			 * target
+			 */
+			x86_mov_membase_reg (code, X86_ESP, this_pos, X86_EDX, 4);=20
+			/* jump to method_ptr() */
+			x86_jump_membase (code, X86_EAX, G_STRUCT_OFFSET (MonoDelegate, method_=
ptr));
+
+			/* mtarget !=3D 0 */=20
+			x86_branch32( br[0], X86_CC_EQ, code - pos[0], TRUE);
+			/*=20
+			 * static delegate methods: we have to remove
+			 * the this pointer from the activation frame
+			 * - I do this creating a new stack frame anx
+			 * copy all arguments except the this pointer
+			 */
+			g_assert ((arg_size & 3) =3D=3D 0);
+			for (i =3D 0; i < (arg_size>>2); i++) {
+				x86_push_membase (code, X86_ESP, (arg_size + this_pos));
+			}
=20
-				if (this_pos =3D=3D 8)=20
-					x86_push_membase (code, X86_ESP, (arg_size + 4));
-			=09
-				x86_call_membase (code, X86_EAX, method_offset);
+			if (this_pos =3D=3D 8)
+				x86_push_membase (code, X86_ESP, (arg_size + 4));
+		=09
+			x86_call_membase (code, X86_EAX, G_STRUCT_OFFSET (MonoDelegate, method_=
ptr));
+			if (arg_size) {
 				if (this_pos =3D=3D 8)=20
 					x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + 4);
 				else
 					x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size);
-			=09
-				x86_ret (code);
-
 			}
=20
+			x86_ret (code);
+	=09
 			g_assert ((code - (guint8*)addr) < (64 + arg_size));
=20
+			if (mono_jit_dump_asm) {
+				char *id =3D g_strdup_printf ("%s.%s_%s", method->klass->name_space,
+							    method->klass->name, method->name);
+				mono_disassemble_code( addr, code - (guint8*)addr, id );
+				g_free (id);
+			}
 		} else {
 			if (mono_debug_handle)=20
 				return NULL;
Index: metadata/appdomain.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/appdomain.c,v
retrieving revision 1.14
diff -u -r1.14 appdomain.c
--- metadata/appdomain.c	2002/03/07 12:41:42	1.14
+++ metadata/appdomain.c	2002/03/11 13:28:39
@@ -199,9 +199,9 @@
                 mono_defaults.corlib, "System", "Array");
 	g_assert (mono_defaults.array_class !=3D 0);
=20
-	mono_defaults.delegate_class =3D mono_class_from_name (
-                mono_defaults.corlib, "System", "Delegate");
-	g_assert (mono_defaults.delegate_class !=3D 0);
+	mono_defaults.multicastdelegate_class =3D mono_class_from_name (
+		mono_defaults.corlib, "System", "MulticastDelegate");
+	g_assert (mono_defaults.multicastdelegate_class !=3D 0 );
=20
 	mono_defaults.typehandle_class =3D mono_class_from_name (
                 mono_defaults.corlib, "System", "RuntimeTypeHandle");
Index: metadata/class.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/class.c,v
retrieving revision 1.90
diff -u -r1.90 class.c
--- metadata/class.c	2002/03/07 06:39:57	1.90
+++ metadata/class.c	2002/03/11 13:28:39
@@ -327,6 +327,7 @@
 	MonoClass *k, *ic;
 	MonoMethod **vtable =3D class->vtable;
 	int i, max_iid, cur_slot =3D 0;
+	static MonoMethod *default_ghc =3D NULL;
=20
 	g_assert (class);
=20
@@ -622,6 +623,22 @@
 						ic->method.count, ic->name_space, ic->name);
 				}
 			}
+		}
+	}
+
+#define GHC_SLOT 2
+
+	if (!default_ghc) {
+		if (class =3D=3D mono_defaults.object_class) {=20
+			default_ghc =3D vtable [GHC_SLOT];
+			g_assert (!strcmp (default_ghc->name, "GetHashCode"));
+		}
+	}
+=09
+	class->ghcimpl =3D 1;
+	if (class !=3D mono_defaults.object_class) {=20
+		if (vtable [GHC_SLOT] =3D=3D default_ghc) {
+			class->ghcimpl =3D 0;
 		}
 	}
 }
Index: metadata/class.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/class.h,v
retrieving revision 1.41
diff -u -r1.41 class.h
--- metadata/class.h	2002/03/07 06:39:57	1.41
+++ metadata/class.h	2002/03/11 13:28:39
@@ -41,6 +41,7 @@
 	guint inited          : 1;
 	guint valuetype       : 1; /* derives from System.ValueType */
 	guint enumtype        : 1; /* derives from System.Enum */
+	guint ghcimpl         : 1; /* class has its own GetHashCode impl */=20
 	guint min_align       : 4;
=20
 	MonoClass  *parent;
Index: metadata/loader.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/loader.c,v
retrieving revision 1.51
diff -u -r1.51 loader.c
--- metadata/loader.c	2002/02/13 07:44:58	1.51
+++ metadata/loader.c	2002/03/11 13:28:40
@@ -225,27 +225,6 @@
 			g_assert (klass !=3D NULL);
 			mono_class_init (klass);
=20
-			/*=20
-			 * FIXME: this is a workaround for the different signatures
-			 * in delegates constructors you get in user code (native int)
-			 * and in mscorlib (native unsigned int)
-			 */
-			if (klass->parent && klass->parent->parent =3D=3D mono_defaults.delegat=
e_class) {
-				for (i =3D 0; i < klass->method.count; ++i) {
-					MonoMethod *m =3D klass->methods [i];
-					if (!strcmp (mname, m->name)) {
-						if (!strcmp (mname, ".ctor")) {
-							/* we assume signature is correct */
-							mono_metadata_free_method_signature (sig);
-							return m;
-						}
-						if (mono_metadata_signature_equal (sig, m->signature)) {
-							mono_metadata_free_method_signature (sig);
-							return m;
-						}
-					}
-				}
-			}
 			/* mostly dumb search for now */
 			for (i =3D 0; i < klass->method.count; ++i) {
 				MonoMethod *m =3D klass->methods [i];
Index: metadata/loader.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/loader.h,v
retrieving revision 1.16
diff -u -r1.16 loader.h
--- metadata/loader.h	2002/02/13 07:44:58	1.16
+++ metadata/loader.h	2002/03/11 13:28:40
@@ -48,7 +48,7 @@
 	MonoClass *string_class;
 	MonoClass *enum_class;
 	MonoClass *array_class;
-	MonoClass *delegate_class;
+	MonoClass *multicastdelegate_class;
 	MonoClass *typehandle_class;
 	MonoClass *fieldhandle_class;
 	MonoClass *methodhandle_class;
Index: metadata/object.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/object.c,v
retrieving revision 1.46
diff -u -r1.46 object.c
--- metadata/object.c	2002/03/08 07:02:28	1.46
+++ metadata/object.c	2002/03/11 13:28:40
@@ -90,13 +90,22 @@
 MonoObject *
 mono_object_new (MonoDomain *domain, MonoClass *klass)
 {
+	static guint32 uoid =3D 0;
 	MonoObject *o;
=20
 	if (!klass->inited)
 		mono_class_init (klass);
=20
-	o =3D mono_object_allocate (klass->instance_size);
-	o->vtable =3D mono_class_vtable (domain, klass);
+
+	if (klass->ghcimpl) {
+		o =3D mono_object_allocate (klass->instance_size);
+		o->vtable =3D mono_class_vtable (domain, klass);
+	} else {
+		o =3D mono_object_allocate (klass->instance_size + 4);
+		*((guint32 *)o) =3D uoid;
+		((char *)o) +=3D 4;
+		o->vtable =3D mono_class_vtable (domain, klass);
+	}
=20
 	return o;
 }
Index: metadata/object.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/object.h,v
retrieving revision 1.40
diff -u -r1.40 object.h
--- metadata/object.h	2002/03/01 13:47:14	1.40
+++ metadata/object.h	2002/03/11 13:28:40
@@ -98,14 +98,6 @@
 	MonoString *param_name;
 } MonoArgumentException;
=20
-typedef struct {
-	MonoObject object;
-	MonoObject *target_type;
-	MonoObject *target;
-	MonoString *method;
-	gpointer    method_ptr;
-} MonoDelegate;
-
 typedef void   (*MonoRuntimeObjectInit) (MonoObject *o);
 typedef gint32 (*MonoRuntimeExecMain)   (MonoMethod *method, MonoArray *ar=
gs);
=20
Index: metadata/reflection.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/reflection.h,v
retrieving revision 1.23
diff -u -r1.23 reflection.h
--- metadata/reflection.h	2002/03/07 12:41:42	1.23
+++ metadata/reflection.h	2002/03/11 13:28:40
@@ -47,6 +47,15 @@
=20
 typedef struct {
 	MonoObject object;
+	MonoObject *target_type;
+	MonoObject *target;
+	MonoString *method_name;
+	gpointer method_ptr;
+	MonoReflectionMethod *method_info;
+} MonoDelegate;
+
+typedef struct {
+	MonoObject object;
 	MonoClass *klass;
 	MonoClassField *field;
 } MonoReflectionField;
Index: metadata/threads.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/threads.c,v
retrieving revision 1.10
diff -u -r1.10 threads.c
--- metadata/threads.c	2002/02/25 11:01:46	1.10
+++ metadata/threads.c	2002/03/11 13:28:40
@@ -119,7 +119,7 @@
 		  this, start);
 #endif
 =09
-	field=3Dmono_class_get_field_from_name(mono_defaults.delegate_class, "met=
hod_ptr");
+	field=3Dmono_class_get_field_from_name(mono_defaults.multicastdelegate_cl=
ass->parent, "method_ptr");
 	start_func=3D *(gpointer *)(((char *)start) + field->offset);
 =09
 	if(start_func=3D=3DNULL) {
Index: metadata/verify.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/metadata/verify.c,v
retrieving revision 1.6
diff -u -r1.6 verify.c
--- metadata/verify.c	2002/03/11 09:55:32	1.6
+++ metadata/verify.c	2002/03/11 13:28:40
@@ -1825,12 +1825,13 @@
 	{NULL, NULL}
 };
=20
-static const FieldDesc=20
+static FieldDesc=20
 delegate_fields[] =3D {
 	{"target_type", G_STRUCT_OFFSET (MonoDelegate, target_type)},
 	{"m_target", G_STRUCT_OFFSET (MonoDelegate, target)},
-	{"method", G_STRUCT_OFFSET (MonoDelegate, method)},
+	{"method_name", G_STRUCT_OFFSET (MonoDelegate, method_name)},
 	{"method_ptr", G_STRUCT_OFFSET (MonoDelegate, method_ptr)},
+	{"method_info", G_STRUCT_OFFSET (MonoDelegate, method_info)},
 	{NULL, 0}
 };
=20
Index: tests/delegate.cs
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mono/mono/tests/delegate.cs,v
retrieving revision 1.3
diff -u -r1.3 delegate.cs
--- tests/delegate.cs	2001/12/20 15:22:08	1.3
+++ tests/delegate.cs	2002/03/11 13:28:40
@@ -36,6 +36,10 @@
 		Console.WriteLine (d3 (3));
 		G (2);
 		test.H (3);
+
+		if (d.Method.Name !=3D "F")
+			return 1;
+	=09
 		return 0;
 	}
 }

--=-dhyjUQnnQ/bhuIJa2RF9
Content-Disposition: attachment; filename=mcs.diff
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1

Index: class/corlib/System/Delegate.cs
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mcs/class/corlib/System/Delegate.cs,v
retrieving revision 1.10
diff -u -r1.10 Delegate.cs
--- class/corlib/System/Delegate.cs	2002/03/05 12:08:17	1.10
+++ class/corlib/System/Delegate.cs	2002/03/11 11:56:16
@@ -3,6 +3,7 @@
 //
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
+//   Daniel Stodden (stodden@in.tum.de)
 //
 // (C) Ximian, Inc.  http://www.ximian.com
 //
@@ -11,6 +12,7 @@
=20
 using System;
 using System.Globalization;
+using System.Reflection;
 using System.Runtime.Serialization;
=20
 namespace System {
@@ -19,8 +21,9 @@
 	public abstract class Delegate : ICloneable, ISerializable {
 		protected Type target_type;
 		protected object m_target;
-		protected string method;
+		protected string method_name;
 		protected IntPtr method_ptr;
+		protected MethodInfo method_info;
=20
 		protected Delegate (object target, string method)
 		{
@@ -33,7 +36,7 @@
 			this.target_type =3D null;
 			this.method_ptr =3D IntPtr.Zero;
 			this.m_target =3D target;
-			this.method =3D method;
+			this.method_name =3D method;
 		}
=20
 		protected Delegate (Type target_type, string method)
@@ -47,16 +50,14 @@
 			this.target_type =3D target_type;
 			this.method_ptr =3D IntPtr.Zero;
 			this.m_target =3D null;
-			this.method =3D method;
+			this.method_name =3D method;
 		}
=20
-#if NOTYET
 		public MethodInfo Method {
 			get {
-				return null;
+				return method_info;
 			}
 		}
-#endif
=20
 		public object Target {
 			get {
@@ -64,23 +65,37 @@
 			}
 		}
=20
-
 		//
 		// Methods
 		//
+
+		public object DynamicInvoke( object[] args )
+		{
+			return DynamicInvokeImpl( args );
+		}
=20
-		public abstract object Clone ();
+		public virtual object DynamicInvokeImpl( object[] args )
+		{
+			return Method.Invoke( m_target, args );
+		}
+
+		public virtual object Clone()
+		{
+			return MemberwiseClone();
+		}
=20
 		public override bool Equals (object o)
 		{
-			if (!(o is System.Delegate))
+			if ( o =3D=3D null )
 				return false;
+		=09
+			if ( o.GetType() !=3D this.GetType() )
+				return false;
=20
 			Delegate d =3D (Delegate) o;
-		=09
 			if ((d.target_type =3D=3D target_type) &&
 			    (d.m_target =3D=3D m_target) &&
-			    (d.method =3D=3D method))
+			    (d.method_name =3D=3D method_name))
 				return true;
=20
 			return false;
@@ -88,7 +103,7 @@
=20
 		public override int GetHashCode ()
 		{
-			return method.GetHashCode ();
+			return method_name.GetHashCode ();
 		}
=20
 		// This is from ISerializable
@@ -98,6 +113,15 @@
 			// TODO: IMPLEMENT ME
 		}
=20
+		public virtual Delegate[] GetInvocationList()
+		{
+			return new Delegate[] { this };
+		}
+
+		/// <symmary>
+		///   Returns a new MulticastDelegate holding the
+		///   concatenated invocation lists of MulticastDelegates a and b
+		/// </symmary>
 		public static Delegate Combine (Delegate a, Delegate b)
 		{
 			if (a =3D=3D null){
@@ -114,14 +138,54 @@
 			return a.CombineImpl (b);
 		}
=20
+		/// <symmary>
+		///   Returns a new MulticastDelegate holding the
+		///   concatenated invocation lists of an Array of MulticastDelegates
+		/// </symmary>
+		public static Delegate Combine( Delegate[] delegates )
+		{
+			Delegate retval =3D null;
+
+			foreach ( Delegate next in delegates ) {
+				retval =3D Combine( retval, next );
+			}
+
+			return retval;
+		}
+
+
 		protected virtual Delegate CombineImpl (Delegate d)
 		{
 			throw new MulticastNotSupportedException ("");
 		}
-
+	=09
 		[MonoTODO]
 		public static Delegate Remove( Delegate source, Delegate value) {
+			if ( source =3D=3D null )
+				return null;
+			=09
+			if ( value =3D=3D null )
+				return source;
+
 			throw new NotImplementedException ();
+		}
+
+		[MonoTODO]
+		protected virtual Delegate RemoveImpl(Delegate d)
+		{
+			throw new NotImplementedException();
+		}
+
+		public static bool operator =3D=3D( Delegate a, Delegate b )
+		{
+			if ( (object)a =3D=3D null )
+				return false;
+			return a.Equals( b );
+		}
+
+		public static bool operator !=3D( Delegate a, Delegate b )
+		{
+			return !(a =3D=3D b);
 		}
 	}
 }
Index: class/corlib/System/MulticastDelegate.cs
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/mcs/class/corlib/System/MulticastDelegate.cs,v
retrieving revision 1.9
diff -u -r1.9 MulticastDelegate.cs
--- class/corlib/System/MulticastDelegate.cs	2002/03/07 12:42:17	1.9
+++ class/corlib/System/MulticastDelegate.cs	2002/03/11 11:56:16
@@ -3,36 +3,40 @@
 //
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
+//   Daniel Stodden (stodden@in.tum.de)
 //
 // (C) Ximian, Inc.  http://www.ximian.com
 //
-// TODO: Mucho left to implement.
+// TODO: Remove Missing
 //
=20
 using System.Globalization;
+
 namespace System {
=20
-	public abstract class MulticastDelegate : Delegate {
+	public abstract class MulticastDelegate : Delegate
+	{
+		private MulticastDelegate prev;
=20
-		Delegate [] invocation_list;
-	=09
 		protected MulticastDelegate (object target, string method)
 			: base (target, method)
 		{
-			invocation_list =3D null;
+			prev =3D null;
 		}
=20
 		protected MulticastDelegate (Type target_type, string method)
 			: base (target_type, method)
 		{
-			invocation_list =3D null;
+			prev =3D null;
 		}
=20
+#if NOTYET
 		private MulticastDelegate (Type target_type, string method, Delegate [] =
list)
 			: base (target_type, method)
 		{
 			invocation_list =3D (Delegate[])list.Clone ();
 		}
+#endif
 	=09
 #if NOTYET
 		public MethodInfo Method {
@@ -42,37 +46,37 @@
 		}
 #endif
=20
+		public override object DynamicInvokeImpl( object[] args )
+		{
+			if ( prev !=3D null )
+				prev.DynamicInvokeImpl( args );
+
+			return base.DynamicInvokeImpl( args );
+		}
+
 		// <remarks>
 		//   Equals: two multicast delegates are equal if their base is equal
 		//   and their invocations list is equal.
 		// </remarks>
 		public override bool Equals (object o)
 		{
-			if (o =3D=3D null)
-				return false;
-
-			if (!(o is System.MulticastDelegate))
-				return false;
-
-			if (!base.Equals (o))
+			if ( ! base.Equals( o ) )
 				return false;
=20
-			MulticastDelegate d =3D (MulticastDelegate) o;
-
-			if (d.invocation_list =3D=3D null){
-				if (invocation_list =3D=3D null)
-					return true;
-				return false;
-			} else if (invocation_list =3D=3D null)
-				return false;
-
-			int i =3D 0;
-			foreach (Delegate del in invocation_list){
-				if (del !=3D d.invocation_list [i++])
+			MulticastDelegate d =3D this;
+			MulticastDelegate c =3D (MulticastDelegate) o;
+			do {
+				if ( d !=3D c )
 					return false;
-			}
-		=09
-			return true;
+			=09
+				c =3D c.prev;
+				d =3D d.prev;
+			} while ( (object)d !=3D null );
+	=09
+			if ( (object)c =3D=3D null )
+				return true;
+
+			return false;
 		}
=20
 		//
@@ -82,35 +86,53 @@
 		{
 			return base.GetHashCode ();
 		}
+	=09
+		// <summary>
+		//   Return, in order of invocation, the invocation list
+		//   of a MulticastDelegate
+		// </summary>
+		public override Delegate[] GetInvocationList()
+		{
+			throw new NotImplementedException();
+		}
=20
 		// <summary>
-		//   Combines this MulticastDelegate with the Delegate `follow'.
-		//   This can combine MulticastDelegates and Delegates
+		//   Combines this MulticastDelegate with the (Multicast)Delegate `follo=
w'.
+		//   This does _not_ combine with Delegates. ECMA states the whole deleg=
ate
+		//   thing should have better been a simple System.Delegate class.
+		//   Compiler generated delegates are always MulticastDelegates.
 		// </summary>
-		[MonoTODO]
-		protected override Delegate CombineImpl (Delegate follow)
+		protected override Delegate CombineImpl( Delegate follow )
 		{
+			MulticastDelegate combined, orig, clone;
 		=09
-			throw new NotImplementedException ();
+			if ( this.GetType() !=3D follow.GetType() )
+				throw new ArgumentException( Locale.GetText("Incompatible Delegate Typ=
es") );
=20
-			// FIXME: Implement me.
-			// This is not as simple to implement, as we can
-			// not create an instance of MulticastDelegate.
-			//
-			// Got to think more about this.
-		}
+			combined =3D (MulticastDelegate)follow.Clone();
=20
-		public static bool operator =3D=3D (MulticastDelegate a, MulticastDelega=
te b) {
-			if ((object)a =3D=3D null) {
-				if ((object)b =3D=3D null)
-					return false;
-				return false;
+			for ( clone =3D combined, orig =3D ((MulticastDelegate)follow).prev;
+			      (object)orig !=3D null; orig =3D orig.prev ) {
+
+				clone.prev =3D (MulticastDelegate)orig.Clone();
+				clone =3D clone.prev;
+			}
+
+			clone.prev =3D (MulticastDelegate)this.Clone();
+
+			for ( clone =3D clone.prev, orig =3D this.prev;
+			      (object)orig !=3D null; orig =3D orig.prev ) {
+
+				clone.prev =3D (MulticastDelegate)orig.Clone();
+				clone =3D clone.prev;
 			}
-			return a.Equals (b);
+
+			return combined;
 		}
=20
-		public static bool operator !=3D (MulticastDelegate a, MulticastDelegate=
 b) {
-			return !(a =3D=3D b);
+		protected override Delegate RemoveImpl( Delegate value )
+		{
+			throw new NotImplementedException();
 		}
 	}
 }

--=-dhyjUQnnQ/bhuIJa2RF9--