Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

imported delegate patches from Daniel, new GetHashCode icalls

svn path=/trunk/mono/; revision=3060
  • Loading branch information...
commit 84d0f82b5fe324220f42978c34e14f14e8e16f69 1 parent 7fd884c
Dietmar Maurer authored
View
3  mono/interpreter/ChangeLog
@@ -1,3 +1,6 @@
+2002-03-11 Dietmar Maurer <dietmar@ximian.com>
+
+ * interp.c (ves_runtime_method): set method_info field
Mon Mar 11 14:48:07 CET 2002 Paolo Molaro <lupus@ximian.com>
View
27 mono/interpreter/interp.c
@@ -533,27 +533,34 @@ ves_runtime_method (MonoInvocation *frame)
{
const char *name = frame->method->name;
MonoObject *obj = (MonoObject*)frame->obj;
- MonoDelegate *delegate = (MonoDelegate*)frame->obj;
+ MonoMulticastDelegate *delegate = (MonoMulticastDelegate*)frame->obj;
MonoInvocation call;
- mono_class_init (mono_defaults.delegate_class);
+ mono_class_init (mono_defaults.multicastdelegate_class);
if (*name == '.' && (strcmp (name, ".ctor") == 0) && obj &&
- mono_object_isinst (obj, mono_defaults.delegate_class)) {
- delegate->target = frame->stack_args[0].data.p;
- delegate->method_ptr = frame->stack_args[1].data.p;
+ mono_object_isinst (obj, mono_defaults.multicastdelegate_class)) {
+ delegate->delegate.target = frame->stack_args[0].data.p;
+ delegate->delegate.method_ptr = frame->stack_args[1].data.p;
+ if (!delegate->delegate.target) {
+ MonoDomain *domain = mono_domain_get ();
+ MonoMethod *m = mono_method_pointer_get (delegate->delegate.method_ptr);
+ delegate->delegate.method_info = mono_method_get_object (domain, m);
+ }
return;
}
if (*name == 'I' && (strcmp (name, "Invoke") == 0) && obj &&
- mono_object_isinst (obj, mono_defaults.delegate_class)) {
- MonoPIFunc func;
+ mono_object_isinst (obj, mono_defaults.multicastdelegate_class)) {
guchar *code;
MonoMethod *method;
- code = (guchar*)delegate->method_ptr;
+ // FIXME: support multicast delegates
+ g_assert (!delegate->prev);
+
+ code = (guchar*)delegate->delegate.method_ptr;
method = mono_method_pointer_get (code);
/* FIXME: check for NULL method */
- INIT_FRAME(&call,frame,delegate->target,frame->stack_args,frame->retval,method);
+ INIT_FRAME(&call,frame,delegate->delegate.target,frame->stack_args,frame->retval,method);
ves_exec_method (&call);
#if 0
if (!method->addr)
@@ -3702,7 +3709,7 @@ output_profile (GList *funcs)
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));
}
}
View
5 mono/jit/ChangeLog
@@ -1,4 +1,9 @@
+2002-03-11 Dietmar Maurer <dietmar@ximian.com>
+ * emit-x86.c (mono_delegate_ctor): use C impl. instead of x86_*
+ macros, included new delegate code from Daniel Stodden.
+
+
Mon Mar 11 14:47:21 CET 2002 Paolo Molaro <lupus@ximian.com>
* jit.c: verify that corlib and runtime are in sync.
View
178 mono/jit/emit-x86.c
@@ -876,6 +876,27 @@ match_debug_method (MonoMethod* method)
return 0;
}
+static void
+mono_delegate_ctor (MonoDelegate *this, MonoObject *target,
+ gpointer addr)
+{
+ MonoDomain *domain = mono_domain_get ();
+ MonoClass *class;
+ MonoJitInfo *ji;
+
+ g_assert (this);
+ g_assert (addr);
+
+ class = this->object.vtable->klass;
+
+ if (!target && (ji = mono_jit_info_table_find (mono_jit_info_table, addr)))
+ this->method_info = mono_method_get_object (domain, ji->method);
+
+ this->target = target;
+ this->method_ptr = addr;
+
+}
+
/**
* arch_compile_method:
* @method: pointer to the method info
@@ -916,51 +937,26 @@ arch_compile_method (MonoMethod *method)
}
if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
- MonoClassField *field;
const char *name = method->name;
- static guint target_offset = 0;
- static guint method_offset = 0;
guint8 *code;
gboolean delegate = FALSE;
- if (method->klass->parent &&
- method->klass->parent->parent == mono_defaults.delegate_class)
+ if (method->klass->parent == mono_defaults.multicastdelegate_class)
delegate = TRUE;
- if (!target_offset) {
- mono_class_init (mono_defaults.delegate_class);
-
- field = mono_class_get_field_from_name (mono_defaults.delegate_class, "m_target");
- target_offset = field->offset;
- field = mono_class_get_field_from_name (mono_defaults.delegate_class, "method_ptr");
- method_offset = field->offset;
- }
-
if (delegate && *name == '.' && (strcmp (name, ".ctor") == 0)) {
- addr = code = g_malloc (32);
- x86_push_reg (code, X86_EBP);
- x86_mov_reg_reg (code, X86_EBP, X86_ESP, 4);
-
- /* load the this pointer */
- x86_mov_reg_membase (code, X86_EAX, X86_EBP, 8, 4);
- /* 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);
- /* 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);
-
- x86_leave (code);
- x86_ret (code);
-
- g_assert ((code - (guint8*)addr) < 32);
-
+ addr = (gpointer)mono_delegate_ctor;
} else if (delegate && *name == 'I' && (strcmp (name, "Invoke") == 0)) {
+ /*
+ * Invoke( args .. ) {
+ * if ( prev )
+ * prev.Invoke();
+ * return this.<m_target>( args );
+ * }
+ */
MonoMethodSignature *csig = method->signature;
- int i, arg_size, target, this_pos = 4;
- guint8 *source;
+ guint8 *br[2], *pos[2];
+ int i, arg_size, this_pos = 4;
if (csig->ret->type == MONO_TYPE_VALUETYPE) {
g_assert (!csig->ret->byref);
@@ -979,50 +975,89 @@ arch_compile_method (MonoMethod *method)
addr = g_malloc (64 + arg_size);
- for (i = 0; i < 2; i ++) {
- int j;
-
- code = 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);
- /* 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);
- source = code;
-
- /* virtual delegate methods: we have to replace the this pointer
- * withe the actual target */
- x86_mov_membase_reg (code, X86_ESP, this_pos, X86_EDX, 4);
- /* jump to method_ptr() */
- x86_jump_membase (code, X86_EAX, method_offset);
-
- /* static delegate methods: we have to remove the this pointer
- * from the activation frame - I do this do creating a new
- * stack frame an copy all arguments except the this pointer */
-
- target = code - source;
- g_assert ((arg_size & 3) == 0);
- for (j = 0; j < (arg_size>>2); j++) {
- x86_push_membase (code, X86_ESP, (arg_size + this_pos));
- }
+ code = addr;
+ /* load the this pointer */
+ x86_mov_reg_membase (code, X86_EAX, X86_ESP, this_pos, 4);
+
+ /* load prev */
+ x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (MonoMulticastDelegate, prev), 4);
+
+ /* prev == 0 ? */
+ x86_alu_reg_imm (code, X86_CMP, X86_EDX, 0);
+ br[0] = code; x86_branch32 (code, X86_CC_EQ, 0, TRUE );
+ pos[0] = code;
+
+ x86_push_reg( code, X86_EAX );
+ /* push args */
+ for ( i = 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 == 8)
+ x86_push_membase (code, X86_ESP, (arg_size + 8));
+ /* recurse */
+ br[1] = code; x86_call_imm( code, 0 );
+ pos[1] = code; x86_call_imm( br[1], addr - pos[1] );
+
+ if (this_pos == 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 );
+
+ /* prev == 0 */
+ x86_branch32( br[0], X86_CC_EQ, code - pos[0], TRUE );
+
+ /* load mtarget */
+ x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (MonoDelegate, target), 4);
+ /* mtarget == 0 ? */
+ x86_alu_reg_imm (code, X86_CMP, X86_EDX, 0);
+ br[0] = code; x86_branch32 (code, X86_CC_EQ, 0, TRUE);
+ pos[0] = code;
+
+ /*
+ * 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);
+ /* jump to method_ptr() */
+ x86_jump_membase (code, X86_EAX, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
+
+ /* mtarget != 0 */
+ x86_branch32( br[0], X86_CC_EQ, code - pos[0], TRUE);
+ /*
+ * 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) == 0);
+ for (i = 0; i < (arg_size>>2); i++) {
+ x86_push_membase (code, X86_ESP, (arg_size + this_pos));
+ }
- if (this_pos == 8)
- x86_push_membase (code, X86_ESP, (arg_size + 4));
-
- x86_call_membase (code, X86_EAX, method_offset);
+ if (this_pos == 8)
+ x86_push_membase (code, X86_ESP, (arg_size + 4));
+
+ x86_call_membase (code, X86_EAX, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
+ if (arg_size) {
if (this_pos == 8)
x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size + 4);
else
x86_alu_reg_imm (code, X86_ADD, X86_ESP, arg_size);
-
- x86_ret (code);
-
}
+ x86_ret (code);
+
g_assert ((code - (guint8*)addr) < (64 + arg_size));
+ if (mono_jit_dump_asm) {
+ char *id = 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)
return NULL;
@@ -1190,7 +1225,6 @@ arch_get_restore_context ()
/* get return address, stored in EDX */
x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, eip), 4);
-
/* restore EBX */
x86_mov_reg_membase (code, X86_EBX, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, ebx), 4);
/* restore EDI */
View
7 mono/metadata/ChangeLog
@@ -1,3 +1,10 @@
+2002-03-12 Dietmar Maurer <dietmar@ximian.com>
+
+ * icall.c (ves_icall_System_Object_GetHashCode): impl.
+
+2002-03-11 Dietmar Maurer <dietmar@ximian.com>
+
+ * icall.c (ves_icall_System_ValueType_GetHashCode): impl.
Mon Mar 11 14:45:42 CET 2002 Paolo Molaro <lupus@ximian.com>
View
6 mono/metadata/appdomain.c
@@ -199,9 +199,9 @@ mono_init (const char *filename)
mono_defaults.corlib, "System", "Array");
g_assert (mono_defaults.array_class != 0);
- mono_defaults.delegate_class = mono_class_from_name (
- mono_defaults.corlib, "System", "Delegate");
- g_assert (mono_defaults.delegate_class != 0);
+ mono_defaults.multicastdelegate_class = mono_class_from_name (
+ mono_defaults.corlib, "System", "MulticastDelegate");
+ g_assert (mono_defaults.multicastdelegate_class != 0 );
mono_defaults.typehandle_class = mono_class_from_name (
mono_defaults.corlib, "System", "RuntimeTypeHandle");
View
17 mono/metadata/class.c
@@ -327,6 +327,7 @@ mono_class_init (MonoClass *class)
MonoClass *k, *ic;
MonoMethod **vtable = class->vtable;
int i, max_iid, cur_slot = 0;
+ static MonoMethod *default_ghc = NULL;
g_assert (class);
@@ -624,6 +625,22 @@ mono_class_init (MonoClass *class)
}
}
}
+
+#define GHC_SLOT 2
+
+ if (!default_ghc) {
+ if (class == mono_defaults.object_class) {
+ default_ghc = vtable [GHC_SLOT];
+ g_assert (!strcmp (default_ghc->name, "GetHashCode"));
+ }
+ }
+
+ class->ghcimpl = 1;
+ if (class != mono_defaults.object_class) {
+ if (vtable [GHC_SLOT] == default_ghc) {
+ class->ghcimpl = 0;
+ }
+ }
}
/**
View
1  mono/metadata/class.h
@@ -41,6 +41,7 @@ struct _MonoClass {
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 */
guint min_align : 4;
MonoClass *parent;
View
44 mono/metadata/icall.c
@@ -509,6 +509,37 @@ ves_icall_System_Object_MemberwiseClone (MonoObject *this)
return mono_object_clone (this);
}
+static gint32
+ves_icall_System_Object_GetHashCode (MonoObject *this)
+{
+ return *((gint32 *)this - 1);
+}
+
+/*
+ * A hash function for value types. I have no idea if this is a good hash
+ * function (its similar to g_str_hash).
+ */
+static gint32
+ves_icall_System_ValueType_GetHashCode (MonoObject *this)
+{
+ gint32 i, size;
+ const char *p;
+ guint h;
+
+ MONO_CHECK_ARG_NULL (this);
+
+ size = this->vtable->klass->instance_size - sizeof (MonoObject);
+
+ p = (char *)this + sizeof (MonoObject);
+
+ for (i = 0; i < size; i++) {
+ h = (h << 5) - h + *p;
+ p++;
+ }
+
+ return h;
+}
+
static MonoReflectionType *
ves_icall_System_Object_GetType (MonoObject *obj)
{
@@ -1643,12 +1674,6 @@ ves_icall_System_CurrentTimeZone_GetTimeZoneData (guint32 year, MonoArray **data
#endif
}
-
-static gpointer
-ves_icall_System_Object_obj_address (MonoObject *this) {
- return this;
-}
-
static gpointer icall_map [] = {
/*
* System.Array
@@ -1669,7 +1694,12 @@ static gpointer icall_map [] = {
*/
"System.Object::MemberwiseClone", ves_icall_System_Object_MemberwiseClone,
"System.Object::GetType", ves_icall_System_Object_GetType,
- "System.Object::obj_address", ves_icall_System_Object_obj_address,
+ "System.Object::GetHashCode", ves_icall_System_Object_GetHashCode,
+
+ /*
+ * System.ValueType
+ */
+ "System.ValueType::GetHashCode", ves_icall_System_ValueType_GetHashCode,
/*
* System.String
View
21 mono/metadata/loader.c
@@ -225,27 +225,6 @@ method_from_memberref (MonoImage *image, guint32 index)
g_assert (klass != NULL);
mono_class_init (klass);
- /*
- * 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 == mono_defaults.delegate_class) {
- for (i = 0; i < klass->method.count; ++i) {
- MonoMethod *m = 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 = 0; i < klass->method.count; ++i) {
MonoMethod *m = klass->methods [i];
View
2  mono/metadata/loader.h
@@ -48,7 +48,7 @@ typedef struct {
MonoClass *string_class;
MonoClass *enum_class;
MonoClass *array_class;
- MonoClass *delegate_class;
+ MonoClass *multicastdelegate_class;
MonoClass *typehandle_class;
MonoClass *fieldhandle_class;
MonoClass *methodhandle_class;
View
14 mono/metadata/object.c
@@ -90,13 +90,23 @@ mono_object_free (MonoObject *o)
MonoObject *
mono_object_new (MonoDomain *domain, MonoClass *klass)
{
+ static guint32 uoid = 0;
MonoObject *o;
if (!klass->inited)
mono_class_init (klass);
- o = mono_object_allocate (klass->instance_size);
- o->vtable = mono_class_vtable (domain, klass);
+
+ if (klass->ghcimpl) {
+ o = mono_object_allocate (klass->instance_size);
+ o->vtable = mono_class_vtable (domain, klass);
+ } else {
+ guint32 *t;
+ t = mono_object_allocate (klass->instance_size + 4);
+ *t = ++uoid;
+ o = (MonoObject *)(++t);
+ o->vtable = mono_class_vtable (domain, klass);
+ }
return o;
}
View
8 mono/metadata/object.h
@@ -98,14 +98,6 @@ typedef struct {
MonoString *param_name;
} MonoArgumentException;
-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 *args);
View
15 mono/metadata/reflection.h
@@ -47,6 +47,21 @@ typedef struct {
typedef struct {
MonoObject object;
+ MonoObject *target_type;
+ MonoObject *target;
+ MonoString *method_name;
+ gpointer method_ptr;
+ MonoReflectionMethod *method_info;
+} MonoDelegate;
+
+typedef struct _MonoMulticastDelegate MonoMulticastDelegate;
+struct _MonoMulticastDelegate {
+ MonoDelegate delegate;
+ MonoMulticastDelegate *prev;
+};
+
+typedef struct {
+ MonoObject object;
MonoClass *klass;
MonoClassField *field;
} MonoReflectionField;
View
2  mono/metadata/threads.c
@@ -119,7 +119,7 @@ HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoObject *this,
this, start);
#endif
- field=mono_class_get_field_from_name(mono_defaults.delegate_class, "method_ptr");
+ field=mono_class_get_field_from_name(mono_defaults.multicastdelegate_class->parent, "method_ptr");
start_func= *(gpointer *)(((char *)start) + field->offset);
if(start_func==NULL) {
View
12 mono/metadata/verify.c
@@ -1825,18 +1825,26 @@ emit_classes_to_check [] = {
{NULL, NULL}
};
-static const FieldDesc
+static FieldDesc
delegate_fields[] = {
{"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}
+};
+
+static FieldDesc
+multicast_delegate_fields[] = {
+ {"prev", G_STRUCT_OFFSET (MonoMulticastDelegate, prev)},
{NULL, 0}
};
static const ClassDesc
system_classes_to_check [] = {
{"Delegate", delegate_fields},
+ {"MulticastDelegate", multicast_delegate_fields},
{NULL, NULL}
};
View
2  mono/metadata/verify.h
@@ -21,7 +21,7 @@ typedef struct {
GSList* mono_image_verify_tables (MonoImage *image, int level);
GSList* mono_method_verify (MonoMethod *method, int level);
void mono_free_verify_list (GSList *list);
-char* mono_verify_corlib ();
+char* mono_verify_corlib (void);
#endif /* __MONO_METADATA_VERIFY_H__ */
View
3  mono/tests/Makefile.am
@@ -81,7 +81,8 @@ TESTSRC= \
appdomain-client.cs \
pointer.cs \
vararg.cs \
- rounding.cs
+ rounding.cs \
+ hashcode.cs
TESTSI=$(TESTSRC:.cs=.exe)
View
4 mono/tests/delegate.cs
@@ -36,6 +36,10 @@ class Test {
Console.WriteLine (d3 (3));
G (2);
test.H (3);
+
+ if (d.Method.Name != "F")
+ return 1;
+
return 0;
}
}
View
28 mono/tests/hashcode.cs
@@ -0,0 +1,28 @@
+using System;
+
+public class X {
+ int a;
+}
+
+public class Test {
+
+ struct test {
+ public int v1;
+ }
+ public static int Main () {
+
+ test a = new test();
+
+ a.v1 = 5;
+
+ Console.WriteLine (a.GetHashCode ());
+
+ X b = new X();
+ X c = new X();
+
+ Console.WriteLine (b.GetHashCode ());
+ Console.WriteLine (c.GetHashCode ());
+
+ return 0;
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.