Wed Jun 25 13:19:25 CEST 2003 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / object.c
1 /*
2  * object.c: Object creation for the Mono runtime
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9 #include <config.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <signal.h>
13 #include <string.h>
14 #include <mono/metadata/mono-endian.h>
15 #include <mono/metadata/tabledefs.h>
16 #include <mono/metadata/tokentype.h>
17 #include <mono/metadata/loader.h>
18 #include <mono/metadata/object.h>
19 #include <mono/metadata/gc-internal.h>
20 #include <mono/metadata/exception.h>
21 #include <mono/metadata/appdomain.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/threadpool.h>
24 #include <mono/metadata/marshal.h>
25 #include "mono/metadata/debug-helpers.h"
26 #include "mono/metadata/marshal.h"
27 #include <mono/metadata/threads.h>
28 #include <mono/metadata/environment.h>
29 #include "mono/metadata/profiler-private.h"
30 #include <mono/os/gc_wrapper.h>
31
32 /*
33  * Enable experimental typed allocation using the GC_gcj_malloc function.
34  */
35 #ifdef HAVE_GC_GCJ_MALLOC
36 #define CREATION_SPEEDUP 1
37 #endif
38
39 void
40 mono_runtime_object_init (MonoObject *this)
41 {
42         int i;
43         MonoMethod *method = NULL;
44         MonoClass *klass = this->vtable->klass;
45
46         for (i = 0; i < klass->method.count; ++i) {
47                 if (!strcmp (".ctor", klass->methods [i]->name) &&
48                     klass->methods [i]->signature->param_count == 0) {
49                         method = klass->methods [i];
50                         break;
51                 }
52         }
53
54         g_assert (method);
55
56         mono_runtime_invoke (method, this, NULL, NULL);
57 }
58
59 /*
60  * mono_runtime_class_init:
61  * @vtable: vtable that needs to be initialized
62  *
63  * This routine calls the class constructor for @vtable.
64  */
65 void
66 mono_runtime_class_init (MonoVTable *vtable)
67 {
68         int i;
69         MonoException *exc;
70         MonoException *exc_to_throw;
71         MonoMethod *method;
72         MonoClass *klass;
73         gchar *full_name;
74         gboolean found;
75
76         MONO_ARCH_SAVE_REGS;
77
78         if (vtable->initialized || vtable->initializing)
79                 return;
80
81         exc = NULL;
82         found = FALSE;
83         klass = vtable->klass;
84         
85         for (i = 0; i < klass->method.count; ++i) {
86                 method = klass->methods [i];
87                 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
88                     (strcmp (".cctor", method->name) == 0)) {
89                         found = TRUE;
90                         break;
91                 }
92         }
93
94         if (found) {
95                 mono_domain_lock (vtable->domain);
96                 /* double check... */
97                 if (vtable->initialized || vtable->initializing)
98                         return;
99                 vtable->initializing = 1;
100                 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
101                 vtable->initialized = 1;
102                 vtable->initializing = 0;
103                 /* FIXME: if the cctor fails, the type must be marked as unusable */
104                 mono_domain_unlock (vtable->domain);
105         } else {
106                 vtable->initialized = 1;
107                 return;
108         }
109
110         if (exc == NULL ||
111             (klass->image == mono_defaults.corlib &&            
112              !strcmp (klass->name_space, "System") &&
113              !strcmp (klass->name, "TypeInitializationException")))
114                 return; /* No static constructor found or avoid infinite loop */
115
116         if (klass->name_space && *klass->name_space)
117                 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
118         else
119                 full_name = g_strdup (klass->name);
120
121         exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
122         g_free (full_name);
123
124         mono_raise_exception (exc_to_throw);
125 }
126
127 static gpointer
128 default_trampoline (MonoMethod *method)
129 {
130         return method;
131 }
132
133 static gpointer
134 default_remoting_trampoline (MonoMethod *method)
135 {
136         g_error ("remoting not installed");
137         return NULL;
138 }
139
140 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
141 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
142
143 void
144 mono_install_trampoline (MonoTrampoline func) 
145 {
146         arch_create_jit_trampoline = func? func: default_trampoline;
147 }
148
149 void
150 mono_install_remoting_trampoline (MonoTrampoline func) 
151 {
152         arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
153 }
154
155 static MonoCompileFunc default_mono_compile_method = NULL;
156
157 void        
158 mono_install_compile_method (MonoCompileFunc func)
159 {
160         default_mono_compile_method = func;
161 }
162
163 gpointer 
164 mono_compile_method (MonoMethod *method)
165 {
166         if (!default_mono_compile_method) {
167                 g_error ("compile method called on uninitialized runtime");
168                 return NULL;
169         }
170         return default_mono_compile_method (method);
171 }
172
173
174 #if 0 && HAVE_BOEHM_GC
175 static void
176 vtable_finalizer (void *obj, void *data) {
177         g_print ("%s finalized (%p)\n", (char*)data, obj);
178 }
179 #endif
180
181 #if CREATION_SPEEDUP
182
183 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
184
185 /*
186  * The vtable is assumed to be reachable by other roots, since vtables
187  * are currently never freed. That might change in the future, but
188  * for now, this is a correct (and worthwhile) optimization.
189  */
190
191 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
192
193 static void
194 mono_class_compute_gc_descriptor (MonoClass *class)
195 {
196         MonoClassField *field;
197         guint64 bitmap;
198         int i;
199         static gboolean gcj_inited = FALSE;
200
201         if (!gcj_inited) {
202                 gcj_inited = TRUE;
203
204                 GC_init_gcj_malloc (5, NULL);
205         }
206
207         if (!class->inited)
208                 mono_class_init (class);
209
210         if (class->gc_descr_inited)
211                 return;
212
213         class->gc_descr_inited = TRUE;
214         class->gc_descr = GC_NO_DESCRIPTOR;
215
216         if (class == mono_defaults.string_class) {
217                 bitmap = GC_HEADER_BITMAP;
218                 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
219         }
220         else if (class->rank) {
221                 mono_class_compute_gc_descriptor (class->element_class);
222
223                 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
224                         bitmap = GC_HEADER_BITMAP;
225                         if (class->rank > 1)
226                                 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
227                         class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
228                 }
229         }
230         else {
231                 static int count = 0;
232                 MonoClass *p;
233                 guint32 pos;
234
235                 /* GC 6.1 has trouble handling 64 bit descriptors... */
236                 if ((class->instance_size / sizeof (gpointer)) > 30) {
237 //                      printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer));
238                         return;
239                 }
240
241                 bitmap = GC_HEADER_BITMAP;
242
243                 count ++;
244
245 //              if (count > 442)
246 //                      return;
247
248 //              printf("KLASS: %s.\n", class->name);
249
250                 for (p = class; p != NULL; p = p->parent) {
251                 for (i = 0; i < p->field.count; ++i) {
252                         field = &p->fields [i];
253                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
254                                 continue;
255                         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
256                                 return;
257
258                         pos = field->offset / sizeof (gpointer);
259                         
260                         if (field->type->byref)
261                                 return;
262
263                         switch (field->type->type) {
264                         case MONO_TYPE_BOOLEAN:
265                         case MONO_TYPE_I1:
266                         case MONO_TYPE_U1:
267                         case MONO_TYPE_I2:
268                         case MONO_TYPE_U2:
269                         case MONO_TYPE_CHAR:
270                         case MONO_TYPE_I4:
271                         case MONO_TYPE_U4:
272                         case MONO_TYPE_I8:
273                         case MONO_TYPE_U8:
274                         case MONO_TYPE_R4:
275                         case MONO_TYPE_R8:
276 //                              printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap);
277                                 break;
278                         case MONO_TYPE_I:
279                         case MONO_TYPE_STRING:
280                         case MONO_TYPE_SZARRAY:
281                         case MONO_TYPE_CLASS:
282                         case MONO_TYPE_OBJECT:
283                         case MONO_TYPE_ARRAY:
284                         case MONO_TYPE_PTR:
285                                 g_assert ((field->offset % sizeof(gpointer)) == 0);
286
287                                 bitmap |= ((guint64)1) << pos;
288 //                              printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap);
289                                 break;
290                         case MONO_TYPE_VALUETYPE: {
291                                 MonoClass *fclass = field->type->data.klass;
292                                 if (!fclass->enumtype) {
293                                         mono_class_compute_gc_descriptor (fclass);
294                                         bitmap |= (fclass->gc_bitmap & ~2) << pos;
295                                 }
296                                 break;
297                         }
298                         default:
299                                 return;
300                         }
301                 }
302                 }
303
304 //              printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap);
305                 class->gc_bitmap = bitmap;
306                 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, class->instance_size / sizeof (gpointer));
307         }
308 }
309 #endif /* CREATION_SPEEDUP */
310
311 static gboolean
312 field_is_thread_static (MonoClass *fklass, MonoClassField *field)
313 {
314         MonoCustomAttrInfo *ainfo;
315         int i;
316         ainfo = mono_custom_attrs_from_field (fklass, field);
317         if (!ainfo)
318                 return FALSE;
319         for (i = 0; i < ainfo->num_attrs; ++i) {
320                 MonoClass *klass = ainfo->attrs [i].ctor->klass;
321                 if (strcmp (klass->name, "ThreadStaticAttribute") == 0 && klass->image == mono_defaults.corlib) {
322                         mono_custom_attrs_free (ainfo);
323                         return TRUE;
324                 }
325         }
326         mono_custom_attrs_free (ainfo);
327         return FALSE;
328 }
329
330 /**
331  * mono_class_vtable:
332  * @domain: the application domain
333  * @class: the class to initialize
334  *
335  * VTables are domain specific because we create domain specific code, and 
336  * they contain the domain specific static class data.
337  */
338 MonoVTable *
339 mono_class_vtable (MonoDomain *domain, MonoClass *class)
340 {
341         MonoVTable *vt;
342         MonoClassField *field;
343         const char *p;
344         char *t;
345         int i, len;
346
347         g_assert (class);
348
349         vt = class->cached_vtable;
350         if (vt && vt->domain == domain)
351                 return vt;
352
353         mono_domain_lock (domain);
354         if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
355                 mono_domain_unlock (domain);
356                 return vt;
357         }
358         
359         if (!class->inited)
360                 mono_class_init (class);
361
362         mono_stats.used_class_count++;
363         mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
364
365         vt = mono_mempool_alloc0 (domain->mp,  sizeof (MonoVTable) + 
366                                   class->vtable_size * sizeof (gpointer));
367         vt->klass = class;
368         vt->domain = domain;
369
370 #if CREATION_SPEEDUP
371         mono_class_compute_gc_descriptor (class);
372         vt->gc_descr = class->gc_descr;
373 #endif
374
375         if (class->class_size) {
376 #if HAVE_BOEHM_GC
377                 vt->data = GC_MALLOC (class->class_size + 8);
378                 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
379                 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
380                 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
381 #else
382                 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
383                 
384 #endif
385                 mono_stats.class_static_data_size += class->class_size + 8;
386         }
387
388         for (i = class->field.first; i < class->field.last; ++i) {
389                 field = &class->fields [i - class->field.first];
390                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
391                         continue;
392                 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
393                         if (field_is_thread_static (class, field)) {
394                                 guint32 size, align, offset;
395                                 size = mono_type_size (field->type, &align);
396                                 offset = mono_threads_alloc_static_data (size, align);
397                                 if (!domain->thread_static_fields)
398                                         domain->thread_static_fields = g_hash_table_new (NULL, NULL);
399                                 g_hash_table_insert (domain->thread_static_fields, field, GUINT_TO_POINTER (offset));
400                                 continue;
401                         }
402                 }
403                 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
404                         MonoClass *fklass = mono_class_from_mono_type (field->type);
405                         t = (char*)vt->data + field->offset;
406                         if (fklass->valuetype) {
407                                 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
408                         } else {
409                                 /* it's a pointer type: add check */
410                                 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
411                                 *t = *(char *)field->data;
412                         }
413                         continue;
414                 }
415                 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
416                         continue;
417                 p = field->def_value->value;
418                 len = mono_metadata_decode_blob_size (p, &p);
419                 t = (char*)vt->data + field->offset;
420                 /* should we check that the type matches? */
421                 switch (field->def_value->type) {
422                 case MONO_TYPE_BOOLEAN:
423                 case MONO_TYPE_U1:
424                 case MONO_TYPE_I1:
425                         *t = *p;
426                         break;
427                 case MONO_TYPE_CHAR:
428                 case MONO_TYPE_U2:
429                 case MONO_TYPE_I2: {
430                         guint16 *val = (guint16*)t;
431                         *val = read16 (p);
432                         break;
433                 }
434                 case MONO_TYPE_U4:
435                 case MONO_TYPE_I4: {
436                         guint32 *val = (guint32*)t;
437                         *val = read32 (p);
438                         break;
439                 }
440                 case MONO_TYPE_U8:
441                 case MONO_TYPE_I8: {
442                         guint64 *val = (guint64*)t;
443                         *val = read64 (p);
444                         break;
445                 }
446                 case MONO_TYPE_R4: {
447                         float *val = (float*)t;
448                         readr4 (p, val);
449                         break;
450                 }
451                 case MONO_TYPE_R8: {
452                         double *val = (double*)t;
453                         readr8 (p, val);
454                         break;
455                 }
456                 case MONO_TYPE_STRING: {
457                         gpointer *val = (gpointer*)t;
458 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
459                         gunichar2 *copy = g_malloc (len);
460                         int j;
461                         for (j = 0; j < len/2; j++) {
462                                 copy [j] = read16 (p);
463                                 p += 2;
464                         }
465                         *val = mono_string_new_utf16 (domain, copy, len/2);
466                         g_free (copy);
467 #else
468                         *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
469 #endif
470                         break;
471                 }
472                 case MONO_TYPE_CLASS:
473                         /* nothing to do, we malloc0 the data and the value can be 0 only */
474                         break;
475                 default:
476                         g_warning ("type 0x%02x should not be in constant table", field->def_value->type);
477                 }
478         }
479
480         vt->max_interface_id = class->max_interface_id;
481         
482         vt->interface_offsets = mono_mempool_alloc0 (domain->mp, 
483                 sizeof (gpointer) * (class->max_interface_id + 1));
484
485         /* initialize interface offsets */
486         for (i = 0; i <= class->max_interface_id; ++i) {
487                 int slot = class->interface_offsets [i];
488                 if (slot >= 0)
489                         vt->interface_offsets [i] = &(vt->vtable [slot]);
490         }
491
492         /* 
493          * arch_create_jit_trampoline () can recursively call this function again
494          * because it compiles icall methods right away.
495          */
496         mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
497         if (!class->cached_vtable)
498                 class->cached_vtable = vt;
499
500         /* initialize vtable */
501         for (i = 0; i < class->vtable_size; ++i) {
502                 MonoMethod *cm;
503                
504                 if ((cm = class->vtable [i]))
505                         vt->vtable [i] = arch_create_jit_trampoline (cm);
506         }
507
508         mono_domain_unlock (domain);
509
510         /* make sure the the parent is initialized */
511         if (class->parent)
512                 mono_class_vtable (domain, class->parent);
513
514         if (class->contextbound)
515                 vt->remote = 1;
516         else
517                 vt->remote = 0;
518
519         return vt;
520 }
521
522 /**
523  * mono_class_proxy_vtable:
524  * @domain: the application domain
525  * @class: the class to proxy
526  *
527  * Creates a vtable for transparent proxies. It is basically
528  * a copy of the real vtable of @class, but all function pointers invoke
529  * the remoting functions, and vtable->klass points to the 
530  * transparent proxy class, and not to @class.
531  */
532 MonoVTable *
533 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
534 {
535         MonoVTable *vt, *pvt;
536         int i, j, vtsize, interface_vtsize = 0;
537         MonoClass* iclass = NULL;
538         MonoClass* k;
539
540         if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
541                 return pvt;
542
543         if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
544                 int method_count;
545                 iclass = class;
546                 class = mono_defaults.marshalbyrefobject_class;
547
548                 method_count = iclass->method.count;
549                 for (i = 0; i < iclass->interface_count; i++)
550                         method_count += iclass->interfaces[i]->method.count;
551
552                 interface_vtsize = method_count * sizeof (gpointer);
553         }
554
555         vt = mono_class_vtable (domain, class);
556         vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
557
558         mono_stats.class_vtable_size += vtsize + interface_vtsize;
559
560         pvt = mono_mempool_alloc (domain->mp, vtsize + interface_vtsize);
561         memcpy (pvt, vt, vtsize);
562
563         pvt->klass = mono_defaults.transparent_proxy_class;
564
565         /* initialize vtable */
566         for (i = 0; i < class->vtable_size; ++i) {
567                 MonoMethod *cm;
568                     
569                 if ((cm = class->vtable [i]))
570                         pvt->vtable [i] = arch_create_remoting_trampoline (cm);
571         }
572
573         if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
574         {
575                 /* create trampolines for abstract methods */
576                 for (k = class; k; k = k->parent) {
577                         for (i = 0; i < k->method.count; i++) {
578                                 int slot = k->methods [i]->slot;
579                                 if (!pvt->vtable [slot]) 
580                                         pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
581                         }
582                 }
583         }
584
585         if (iclass)
586         {
587                 int slot;
588                 MonoClass* interf;
589
590                 pvt->max_interface_id = iclass->max_interface_id;
591                 
592                 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp, 
593                                 sizeof (gpointer) * (pvt->max_interface_id + 1));
594
595                 /* Create trampolines for the methods of the interfaces */
596                 slot = class->vtable_size;
597                 interf = iclass;
598                 i = -1;
599                 do {
600                         pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
601
602                         for (j = 0; j < interf->method.count; ++j) {
603                                 MonoMethod *cm = interf->methods [j];
604                                 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
605                         }
606                         slot += interf->method.count;
607                         if (++i < iclass->interface_count) interf = iclass->interfaces[i];
608                         else interf = NULL;
609                         
610                 } while (interf);
611
612                 class = iclass;
613         }
614         else
615         {
616                 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp, 
617                                 sizeof (gpointer) * (pvt->max_interface_id + 1));
618
619                 /* initialize interface offsets */
620                 for (i = 0; i <= class->max_interface_id; ++i) {
621                         int slot = class->interface_offsets [i];
622                         if (slot >= 0)
623                                 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
624                 }
625         }
626
627         mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
628
629         return pvt;
630 }
631
632 /*
633  * Retrieve the MonoMethod that would to be called on obj if obj is passed as
634  * the instance of a callvirt of method.
635  */
636 MonoMethod*
637 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
638         MonoClass *klass;
639         MonoMethod **vtable;
640         gboolean is_proxy;
641         MonoMethod *res;
642
643         klass = mono_object_class (obj);
644         if (klass == mono_defaults.transparent_proxy_class) {
645                 klass = ((MonoTransparentProxy *)obj)->klass;
646                 is_proxy = TRUE;
647         } else {
648                 is_proxy = FALSE;
649         }
650
651         if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
652                         return method;
653
654         vtable = klass->vtable;
655
656         /* check method->slot is a valid index: perform isinstance? */
657         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
658                 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
659         } else {
660                 res = vtable [method->slot];
661         }
662         g_assert (res);
663
664         if (is_proxy)
665                 return mono_marshal_get_remoting_invoke (res);
666         
667         return res;
668 }
669
670 static MonoObject*
671 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
672 {
673         g_error ("runtime invoke called on uninitialized runtime");
674         return NULL;
675 }
676
677 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
678
679 MonoObject*
680 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
681 {
682         return default_mono_runtime_invoke (method, obj, params, exc);
683 }
684
685 static void
686 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
687         int t;
688         if (type->byref) {
689                 gpointer *p = (gpointer*)dest;
690                 *p = value;
691                 return;
692         }
693         t = type->type;
694 handle_enum:
695         switch (t) {
696         case MONO_TYPE_BOOLEAN:
697         case MONO_TYPE_I1:
698         case MONO_TYPE_U1: {
699                 guint8 *p = (guint8*)dest;
700                 *p = *(guint8*)value;
701                 return;
702         }
703         case MONO_TYPE_I2:
704         case MONO_TYPE_U2:
705         case MONO_TYPE_CHAR: {
706                 guint16 *p = (guint16*)dest;
707                 *p = *(guint16*)value;
708                 return;
709         }
710 #if SIZEOF_VOID_P == 4
711         case MONO_TYPE_I:
712         case MONO_TYPE_U:
713 #endif
714         case MONO_TYPE_I4:
715         case MONO_TYPE_U4: {
716                 gint32 *p = (gint32*)dest;
717                 *p = *(gint32*)value;
718                 return;
719         }
720 #if SIZEOF_VOID_P == 8
721         case MONO_TYPE_I:
722         case MONO_TYPE_U:
723 #endif
724         case MONO_TYPE_I8:
725         case MONO_TYPE_U8: {
726                 gint64 *p = (gint64*)dest;
727                 *p = *(gint64*)value;
728                 return;
729         }
730         case MONO_TYPE_R4: {
731                 float *p = (float*)dest;
732                 *p = *(float*)value;
733                 return;
734         }
735         case MONO_TYPE_R8: {
736                 double *p = (double*)dest;
737                 *p = *(double*)value;
738                 return;
739         }
740         case MONO_TYPE_STRING:
741         case MONO_TYPE_SZARRAY:
742         case MONO_TYPE_CLASS:
743         case MONO_TYPE_OBJECT:
744         case MONO_TYPE_ARRAY:
745         case MONO_TYPE_PTR: {
746                 gpointer *p = (gpointer*)dest;
747                 *p = deref_pointer? *(gpointer*)value: value;
748                 return;
749         }
750         case MONO_TYPE_VALUETYPE:
751                 if (type->data.klass->enumtype) {
752                         t = type->data.klass->enum_basetype->type;
753                         goto handle_enum;
754                 } else {
755                         int size;
756                         size = mono_class_value_size (type->data.klass, NULL);
757                         memcpy (dest, value, size);
758                 }
759                 return;
760         default:
761                 g_warning ("got type %x", type->type);
762                 g_assert_not_reached ();
763         }
764 }
765
766 void
767 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
768 {
769         void *dest;
770
771         g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
772
773         dest = (char*)obj + field->offset;
774         set_value (field->type, dest, value, FALSE);
775 }
776
777 void
778 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
779 {
780         void *dest;
781
782         g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
783
784         dest = (char*)vt->data + field->offset;
785         set_value (field->type, dest, value, FALSE);
786 }
787
788 void
789 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
790 {
791         void *src;
792
793         g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
794
795         src = (char*)obj + field->offset;
796         set_value (field->type, value, src, TRUE);
797 }
798
799 void
800 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
801 {
802         void *src;
803
804         g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
805
806         src = (char*)vt->data + field->offset;
807         set_value (field->type, value, src, TRUE);
808 }
809
810 void
811 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
812 {
813         default_mono_runtime_invoke (prop->set, obj, params, exc);
814 }
815
816 MonoObject*
817 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
818 {
819         return default_mono_runtime_invoke (prop->get, obj, params, exc);
820 }
821
822
823 MonoMethod *
824 mono_get_delegate_invoke (MonoClass *klass)
825 {
826         MonoMethod *im;
827         int i;
828
829         im = NULL;
830
831         for (i = 0; i < klass->method.count; ++i) {
832                 if (klass->methods [i]->name[0] == 'I' && 
833                     !strcmp ("Invoke", klass->methods [i]->name)) {
834                         im = klass->methods [i];
835                 }
836         }
837
838         g_assert (im);
839
840         return im;
841 }
842
843 MonoObject*
844 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
845 {
846         MonoMethod *im;
847
848         im = mono_get_delegate_invoke (delegate->vtable->klass);
849         g_assert (im);
850
851         return mono_runtime_invoke (im, delegate, params, exc);
852 }
853
854 static MonoArray* main_args;
855
856 MonoArray*
857 mono_runtime_get_main_args (void)
858 {
859         return main_args;
860 }
861
862 /*
863  * Execute a standard Main() method (argc/argv contains the
864  * executable name). This method also sets the command line argument value
865  * needed by System.Environment.
866  */
867 int
868 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
869                        MonoObject **exc)
870 {
871         int i;
872         MonoArray *args = NULL;
873         MonoDomain *domain = mono_domain_get ();
874
875         main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
876
877         if (!g_path_is_absolute (argv [0])) {
878                 gchar *basename = g_path_get_basename (argv [0]);
879                 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
880                                                     basename,
881                                                     NULL);
882                 
883                 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, fullpath));
884                 g_free (fullpath);
885                 g_free (basename);
886         } else {
887                 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, argv [0]));
888         }
889
890         for (i = 1; i < argc; ++i) {
891                 MonoString *arg = mono_string_new (domain, argv [i]);
892                 mono_array_set (main_args, gpointer, i, arg);
893         }
894         argc--;
895         argv++;
896         if (method->signature->param_count) {
897                 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
898                 for (i = 0; i < argc; ++i) {
899                         MonoString *arg = mono_string_new (domain, argv [i]);
900                         mono_array_set (args, gpointer, i, arg);
901                 }
902         } else {
903                 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
904         }
905         
906         mono_assembly_set_main (method->klass->image->assembly);
907
908         return mono_runtime_exec_main (method, args, exc);
909 }
910
911 /* Used in mono_unhandled_exception */
912 static MonoObject *
913 create_unhandled_exception_eventargs (MonoObject *exc)
914 {
915         MonoClass *klass;
916         gpointer args [2];
917         MonoMethod *method;
918         MonoBoolean is_terminating = TRUE;
919         MonoObject *obj;
920         gint i;
921
922         klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
923         g_assert (klass);
924
925         mono_class_init (klass);
926
927         /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
928         for (i = 0; i < klass->method.count; ++i) {
929                 method = klass->methods [i];
930                 if (!strcmp (".ctor", method->name) &&
931                     method->signature->param_count == 2 &&
932                     method->flags & METHOD_ATTRIBUTE_PUBLIC)
933                         break;
934                 method = NULL;
935         }
936
937         g_assert (method);
938
939         args [0] = exc;
940         args [1] = &is_terminating;
941
942         obj = mono_object_new (mono_domain_get (), klass);
943         mono_runtime_invoke (method, obj, args, NULL);
944
945         return obj;
946 }
947
948 /*
949  * We call this function when we detect an unhandled exception
950  * in the default domain.
951  * It invokes the * UnhandledException event in AppDomain or prints
952  * a warning to the console 
953  */
954 void
955 mono_unhandled_exception (MonoObject *exc)
956 {
957         MonoDomain *domain = mono_domain_get ();
958         MonoClassField *field;
959         MonoObject *delegate;
960         
961         field=mono_class_get_field_from_name(mono_defaults.appdomain_class, 
962                                              "UnhandledException");
963         g_assert (field);
964
965         if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
966                 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset); 
967
968                 /* set exitcode only in the main thread? */
969                 mono_environment_exitcode_set (1);
970                 if (domain != mono_root_domain || !delegate) {
971                         mono_print_unhandled_exception (exc);
972                 } else {
973                         MonoObject *e = NULL;
974                         gpointer pa [2];
975
976                         pa [0] = domain->domain;
977                         pa [1] = create_unhandled_exception_eventargs (exc);
978                         mono_runtime_delegate_invoke (delegate, pa, &e);
979                         
980                         if (e) {
981                                 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
982                                 g_warning ("exception inside UnhandledException handler: %s\n", msg);
983                                 g_free (msg);
984                         }
985                 }
986         }
987 }
988
989 /*
990  * Launch a new thread to start all setup that requires managed code
991  * to be executed.
992  *
993  * main_func is called back from the thread with main_args as the
994  * parameter.  The callback function is expected to start Main()
995  * eventually.  This function then waits for all managed threads to
996  * finish.
997  */
998 void
999 mono_runtime_exec_managed_code (MonoDomain *domain,
1000                                 MonoMainThreadFunc main_func,
1001                                 gpointer main_args)
1002 {
1003         mono_thread_create (domain, main_func, main_args);
1004
1005         mono_thread_manage ();
1006 }
1007
1008 /*
1009  * Execute a standard Main() method (args doesn't contain the
1010  * executable name).
1011  */
1012 int
1013 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1014 {
1015         MonoDomain *domain;
1016         gpointer pa [1];
1017         int rval;
1018
1019         g_assert (args);
1020
1021         pa [0] = args;
1022
1023         domain = mono_object_domain (args);
1024         if (!domain->entry_assembly) {
1025                 domain->entry_assembly = method->klass->image->assembly;
1026                 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
1027         }
1028
1029         /* FIXME: check signature of method */
1030         if (method->signature->ret->type == MONO_TYPE_I4) {
1031                 MonoObject *res;
1032                 res = mono_runtime_invoke (method, NULL, pa, exc);
1033                 if (!exc || !*exc)
1034                         rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1035                 else
1036                         rval = -1;
1037
1038                 mono_environment_exitcode_set (rval);
1039         } else {
1040                 mono_runtime_invoke (method, NULL, pa, exc);
1041                 if (!exc || !*exc)
1042                         rval = 0;
1043                 else {
1044                         /* If the return type of Main is void, only
1045                          * set the exitcode if an exception was thrown
1046                          * (we don't want to blow away an
1047                          * explicitly-set exit code)
1048                          */
1049                         rval = -1;
1050                         mono_environment_exitcode_set (rval);
1051                 }
1052         }
1053
1054         return rval;
1055 }
1056
1057 void
1058 mono_install_runtime_invoke (MonoInvokeFunc func)
1059 {
1060         default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1061 }
1062
1063 MonoObject*
1064 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1065                            MonoObject **exc)
1066 {
1067         MonoMethodSignature *sig = method->signature;
1068         gpointer *pa = NULL;
1069         int i;
1070                 
1071         if (NULL != params) {
1072                 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1073                 for (i = 0; i < mono_array_length (params); i++) {
1074                         if (sig->params [i]->byref) {
1075                                 /* nothing to do */
1076                         }
1077
1078                         switch (sig->params [i]->type) {
1079                         case MONO_TYPE_U1:
1080                         case MONO_TYPE_I1:
1081                         case MONO_TYPE_BOOLEAN:
1082                         case MONO_TYPE_U2:
1083                         case MONO_TYPE_I2:
1084                         case MONO_TYPE_CHAR:
1085                         case MONO_TYPE_U:
1086                         case MONO_TYPE_I:
1087                         case MONO_TYPE_U4:
1088                         case MONO_TYPE_I4:
1089                         case MONO_TYPE_U8:
1090                         case MONO_TYPE_I8:
1091                         case MONO_TYPE_R4:
1092                         case MONO_TYPE_R8:
1093                         case MONO_TYPE_VALUETYPE:
1094                                 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1095                                 break;
1096                         case MONO_TYPE_STRING:
1097                         case MONO_TYPE_OBJECT:
1098                         case MONO_TYPE_CLASS:
1099                         case MONO_TYPE_ARRAY:
1100                         case MONO_TYPE_SZARRAY:
1101                                 if (sig->params [i]->byref)
1102                                         pa [i] = &(((gpointer *)params->vector)[i]);
1103                                 else
1104                                         pa [i] = (char *)(((gpointer *)params->vector)[i]);
1105                                 break;
1106                         default:
1107                                 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1108                         }
1109                 }
1110         }
1111
1112         if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1113                 if (!obj) {
1114                         obj = mono_object_new (mono_domain_get (), method->klass);
1115                         if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1116                                 method = mono_marshal_get_remoting_invoke (method->klass->vtable [method->slot]);
1117                         }
1118                 }
1119                 mono_runtime_invoke (method, obj, pa, exc);
1120                 return obj;
1121         } else
1122                 return mono_runtime_invoke (method, obj, pa, exc);
1123 }
1124
1125 G_GNUC_NORETURN static void
1126 out_of_memory (size_t size)
1127 {
1128         /* 
1129          * we could allocate at program startup some memory that we could release 
1130          * back to the system at this point if we're really low on memory (ie, size is
1131          * lower than the memory we set apart)
1132          */
1133         MonoException * ex = mono_exception_from_name (mono_defaults.corlib, "System", "OutOfMemoryException");
1134         mono_raise_exception (ex);
1135 }
1136
1137 /**
1138  * mono_object_allocate:
1139  * @size: number of bytes to allocate
1140  *
1141  * This is a very simplistic routine until we have our GC-aware
1142  * memory allocator. 
1143  *
1144  * Returns: an allocated object of size @size, or NULL on failure.
1145  */
1146 static void *
1147 mono_object_allocate (size_t size)
1148 {
1149 #if HAVE_BOEHM_GC
1150         /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1151         void *o = GC_MALLOC (size);
1152 #else
1153         void *o = calloc (1, size);
1154 #endif
1155         mono_stats.new_object_count++;
1156
1157         if (!o)
1158                 out_of_memory (size);
1159         return o;
1160 }
1161
1162 #if CREATION_SPEEDUP
1163 static void *
1164 mono_object_allocate_spec (size_t size, void *gcdescr)
1165 {
1166         /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1167         void *o = GC_GCJ_MALLOC (size, gcdescr);
1168         mono_stats.new_object_count++;
1169
1170         if (!o)
1171                 out_of_memory (size);
1172         return o;
1173 }
1174 #endif
1175
1176 /**
1177  * mono_object_free:
1178  *
1179  * Frees the memory used by the object.  Debugging purposes
1180  * only, as we will have our GC system.
1181  */
1182 void
1183 mono_object_free (MonoObject *o)
1184 {
1185 #if HAVE_BOEHM_GC
1186         g_error ("mono_object_free called with boehm gc.");
1187 #else
1188         MonoClass *c = o->vtable->klass;
1189         
1190         memset (o, 0, c->instance_size);
1191         free (o);
1192 #endif
1193 }
1194
1195 /**
1196  * mono_object_new:
1197  * @klass: the class of the object that we want to create
1198  *
1199  * Returns: A newly created object whose definition is
1200  * looked up using @klass
1201  */
1202 MonoObject *
1203 mono_object_new (MonoDomain *domain, MonoClass *klass)
1204 {
1205         MONO_ARCH_SAVE_REGS;
1206         return mono_object_new_specific (mono_class_vtable (domain, klass));
1207 }
1208
1209 /**
1210  * mono_object_new_specific:
1211  * @vtable: the vtable of the object that we want to create
1212  *
1213  * Returns: A newly created object with class and domain specified
1214  * by @vtable
1215  */
1216 MonoObject *
1217 mono_object_new_specific (MonoVTable *vtable)
1218 {
1219         MonoObject *o;
1220
1221         MONO_ARCH_SAVE_REGS;
1222         
1223         if (vtable->remote)
1224         {
1225                 gpointer pa [1];
1226                 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1227
1228                 if (im == NULL) {
1229                         MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1230                         int i;
1231
1232                         if (!klass->inited)
1233                                 mono_class_init (klass);
1234
1235                         for (i = 0; i < klass->method.count; ++i) {
1236                                 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1237                                         klass->methods [i]->signature->param_count == 1) {
1238                                         im = klass->methods [i];
1239                                         break;
1240                                 }
1241                         }
1242                         g_assert (im);
1243                         vtable->domain->create_proxy_for_type_method = im;
1244                 }
1245         
1246                 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1247
1248                 o = mono_runtime_invoke (im, NULL, pa, NULL);           
1249                 if (o != NULL) return o;
1250         }
1251
1252         return mono_object_new_alloc_specific (vtable);
1253 }
1254
1255 MonoObject *
1256 mono_object_new_alloc_specific (MonoVTable *vtable)
1257 {
1258         MonoObject *o;
1259
1260 #if CREATION_SPEEDUP
1261         if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1262                 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1263         } else {
1264 //              printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1265                 o = mono_object_allocate (vtable->klass->instance_size);
1266                 o->vtable = vtable;
1267         }
1268 #else
1269         o = mono_object_allocate (vtable->klass->instance_size);
1270         o->vtable = vtable;
1271 #endif
1272         if (vtable->klass->has_finalize)
1273                 mono_object_register_finalizer (o);
1274         
1275         mono_profiler_allocation (o, vtable->klass);
1276         return o;
1277 }
1278
1279 /**
1280  * mono_object_new_from_token:
1281  * @image: Context where the type_token is hosted
1282  * @token: a token of the type that we want to create
1283  *
1284  * Returns: A newly created object whose definition is
1285  * looked up using @token in the @image image
1286  */
1287 MonoObject *
1288 mono_object_new_from_token  (MonoDomain *domain, MonoImage *image, guint32 token)
1289 {
1290         MonoClass *class;
1291
1292         class = mono_class_get (image, token);
1293
1294         return mono_object_new (domain, class);
1295 }
1296
1297
1298 /**
1299  * mono_object_clone:
1300  * @obj: the object to clone
1301  *
1302  * Returns: A newly created object who is a shallow copy of @obj
1303  */
1304 MonoObject *
1305 mono_object_clone (MonoObject *obj)
1306 {
1307         MonoObject *o;
1308         int size;
1309
1310         size = obj->vtable->klass->instance_size;
1311         o = mono_object_allocate (size);
1312         mono_profiler_allocation (o, obj->vtable->klass);
1313
1314         memcpy (o, obj, size);
1315
1316         if (obj->vtable->klass->has_finalize)
1317                 mono_object_register_finalizer (o);
1318         return o;
1319 }
1320
1321 /**
1322  * mono_array_clone:
1323  * @array: the array to clone
1324  *
1325  * Returns: A newly created array who is a shallow copy of @array
1326  */
1327 MonoArray*
1328 mono_array_clone (MonoArray *array)
1329 {
1330         MonoArray *o;
1331         int size, i;
1332         guint32 *sizes;
1333         MonoClass *klass = array->obj.vtable->klass;
1334
1335         MONO_ARCH_SAVE_REGS;
1336
1337         if (array->bounds == NULL) {
1338                 size = mono_array_length (array);
1339                 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1340                                          klass, &size, NULL);
1341
1342                 size *= mono_array_element_size (klass);
1343                 memcpy (o, array, sizeof (MonoArray) + size);
1344
1345                 return o;
1346         }
1347         
1348         sizes = alloca (klass->rank * sizeof(guint32) * 2);
1349         size = mono_array_element_size (klass);
1350         for (i = 0; i < klass->rank; ++i) {
1351                 sizes [i] = array->bounds [i].length;
1352                 size *= array->bounds [i].length;
1353                 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1354         }
1355         o = mono_array_new_full (((MonoObject *)array)->vtable->domain, 
1356                                  klass, sizes, sizes + klass->rank);
1357         memcpy (o, array, sizeof(MonoArray) + size);
1358
1359         return o;
1360 }
1361
1362 /* helper macros to check for overflow when calculating the size of arrays */
1363 #define MYGUINT32_MAX 4294967295U
1364 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1365         (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1366 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1367         ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1368         (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1369
1370 /*
1371  * mono_array_new_full:
1372  * @domain: domain where the object is created
1373  * @array_class: array class
1374  * @lengths: lengths for each dimension in the array
1375  * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1376  *
1377  * This routine creates a new array objects with the given dimensions,
1378  * lower bounds and type.
1379  */
1380 MonoArray*
1381 mono_array_new_full (MonoDomain *domain, MonoClass *array_class, 
1382                      guint32 *lengths, guint32 *lower_bounds)
1383 {
1384         guint32 byte_len, len;
1385         MonoObject *o;
1386         MonoArray *array;
1387         MonoArrayBounds *bounds;
1388         MonoVTable *vtable;
1389         int i;
1390
1391         if (!array_class->inited)
1392                 mono_class_init (array_class);
1393
1394         byte_len = mono_array_element_size (array_class);
1395         len = 1;
1396
1397         if (array_class->rank == 1 &&
1398             (lower_bounds == NULL || lower_bounds [0] == 0)) {
1399                 bounds = NULL;
1400                 len = lengths [0];
1401         } else {
1402         #if HAVE_BOEHM_GC
1403                 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1404         #else
1405                 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1406         #endif
1407                 for (i = 0; i < array_class->rank; ++i) {
1408                         bounds [i].length = lengths [i];
1409                         if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1410                                 out_of_memory (MYGUINT32_MAX);
1411                         len *= lengths [i];
1412                 }
1413
1414                 if (lower_bounds)
1415                         for (i = 0; i < array_class->rank; ++i)
1416                                 bounds [i].lower_bound = lower_bounds [i];
1417         }
1418
1419         if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1420                 out_of_memory (MYGUINT32_MAX);
1421         byte_len *= len;
1422         if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1423                 out_of_memory (MYGUINT32_MAX);
1424         byte_len += sizeof (MonoArray);
1425         /* 
1426          * Following three lines almost taken from mono_object_new ():
1427          * they need to be kept in sync.
1428          */
1429         vtable = mono_class_vtable (domain, array_class);
1430 #if CREATION_SPEEDUP
1431         if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1432                 o = mono_object_allocate_spec (byte_len, vtable);
1433         else {
1434                 o = mono_object_allocate (byte_len);
1435                 o->vtable = vtable;
1436         }
1437 #else
1438         o = mono_object_allocate (byte_len);
1439         o->vtable = vtable;
1440 #endif
1441
1442         array = (MonoArray*)o;
1443
1444         array->bounds = bounds;
1445         array->max_length = len;
1446
1447         mono_profiler_allocation (o, array_class);
1448
1449         return array;
1450 }
1451
1452 /*
1453  * mono_array_new:
1454  * @domain: domain where the object is created
1455  * @eclass: element class
1456  * @n: number of array elements
1457  *
1458  * This routine creates a new szarray with @n elements of type @eclass.
1459  */
1460 MonoArray *
1461 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1462 {
1463         MonoClass *ac;
1464
1465         MONO_ARCH_SAVE_REGS;
1466
1467         ac = mono_array_class_get (&eclass->byval_arg, 1);
1468         g_assert (ac != NULL);
1469
1470         return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1471 }
1472
1473 /*
1474  * mono_array_new_specific:
1475  * @vtable: a vtable in the appropriate domain for an initialized class
1476  * @n: number of array elements
1477  *
1478  * This routine is a fast alternative to mono_array_new() for code which
1479  * can be sure about the domain it operates in.
1480  */
1481 MonoArray *
1482 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1483 {
1484         MonoObject *o;
1485         MonoArray *ao;
1486         guint32 byte_len, elem_size;
1487
1488         MONO_ARCH_SAVE_REGS;
1489
1490         elem_size = mono_array_element_size (vtable->klass);
1491         if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1492                 out_of_memory (MYGUINT32_MAX);
1493         byte_len = n * elem_size;
1494         if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1495                 out_of_memory (MYGUINT32_MAX);
1496         byte_len += sizeof (MonoArray);
1497 #if CREATION_SPEEDUP
1498         if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1499                 o = mono_object_allocate_spec (byte_len, vtable);
1500         } else {
1501 //              printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1502                 o = mono_object_allocate (byte_len);
1503                 o->vtable = vtable;
1504         }
1505 #else
1506         o = mono_object_allocate (byte_len);
1507         o->vtable = vtable;
1508 #endif
1509
1510         ao = (MonoArray *)o;
1511         ao->bounds = NULL;
1512         ao->max_length = n;
1513         mono_profiler_allocation (o, vtable->klass);
1514
1515         return ao;
1516 }
1517
1518 /**
1519  * mono_string_new_utf16:
1520  * @text: a pointer to an utf16 string
1521  * @len: the length of the string
1522  *
1523  * Returns: A newly created string object which contains @text.
1524  */
1525 MonoString *
1526 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1527 {
1528         MonoString *s;
1529         
1530         s = mono_string_new_size (domain, len);
1531         g_assert (s != NULL);
1532
1533         memcpy (mono_string_chars (s), text, len * 2);
1534
1535         return s;
1536 }
1537
1538 /**
1539  * mono_string_new_size:
1540  * @text: a pointer to an utf16 string
1541  * @len: the length of the string
1542  *
1543  * Returns: A newly created string object of @len
1544  */
1545 MonoString *
1546 mono_string_new_size (MonoDomain *domain, gint32 len)
1547 {
1548         MonoString *s;
1549         MonoVTable *vtable;
1550
1551         vtable = mono_class_vtable (domain, mono_defaults.string_class);
1552
1553 #if CREATION_SPEEDUP
1554         s = mono_object_allocate_spec (sizeof (MonoString) + ((len + 1) * 2), vtable);
1555 #else
1556         s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1557         s->object.vtable = vtable;
1558 #endif
1559
1560         s->length = len;
1561         mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
1562
1563         return s;
1564 }
1565
1566 /*
1567  * mono_string_new_len:
1568  * @text: a pointer to an utf8 string
1569  * @length: number of bytes in @text to consider
1570  *
1571  * Returns: A newly created string object which contains @text.
1572  */
1573 MonoString*
1574 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1575 {
1576         GError *error = NULL;
1577         MonoString *o = NULL;
1578         guint16 *ut;
1579         glong items_written;
1580
1581         ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1582
1583         if (!error)
1584                 o = mono_string_new_utf16 (domain, ut, items_written);
1585         else 
1586                 g_error_free (error);
1587
1588         g_free (ut);
1589
1590         return o;
1591 }
1592
1593 /**
1594  * mono_string_new:
1595  * @text: a pointer to an utf8 string
1596  *
1597  * Returns: A newly created string object which contains @text.
1598  */
1599 MonoString*
1600 mono_string_new (MonoDomain *domain, const char *text)
1601 {
1602         GError *error = NULL;
1603         MonoString *o = NULL;
1604         guint16 *ut;
1605         glong items_written;
1606         int l;
1607
1608         l = strlen (text);
1609         
1610         ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1611
1612         if (!error)
1613                 o = mono_string_new_utf16 (domain, ut, items_written);
1614         else 
1615                 g_error_free (error);
1616
1617         g_free (ut);
1618
1619         return o;
1620 }
1621
1622 /*
1623  * mono_string_new_wrapper:
1624  * @text: pointer to utf8 characters.
1625  *
1626  * Helper function to create a string object from @text in the current domain.
1627  */
1628 MonoString*
1629 mono_string_new_wrapper (const char *text)
1630 {
1631         MonoDomain *domain = mono_domain_get ();
1632
1633         MONO_ARCH_SAVE_REGS;
1634
1635         if (text)
1636                 return mono_string_new (domain, text);
1637
1638         return NULL;
1639 }
1640
1641 /**
1642  * mono_value_box:
1643  * @class: the class of the value
1644  * @value: a pointer to the unboxed data
1645  *
1646  * Returns: A newly created object which contains @value.
1647  */
1648 MonoObject *
1649 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1650 {
1651         MonoObject *res;
1652         int size;
1653         MonoVTable *vtable;
1654
1655         g_assert (class->valuetype);
1656
1657         vtable = mono_class_vtable (domain, class);
1658         size = mono_class_instance_size (class);
1659         res = mono_object_allocate (size);
1660         res->vtable = vtable;
1661         mono_profiler_allocation (res, class);
1662
1663         size = size - sizeof (MonoObject);
1664
1665 #if NO_UNALIGNED_ACCESS
1666         memcpy ((char *)res + sizeof (MonoObject), value, size);
1667 #else
1668         switch (size) {
1669         case 1:
1670                 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
1671                 break;
1672         case 2:
1673                 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
1674                 break;
1675         case 4:
1676                 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
1677                 break;
1678         case 8:
1679                 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
1680                 break;
1681         default:
1682                 memcpy ((char *)res + sizeof (MonoObject), value, size);
1683         }
1684 #endif
1685         if (class->has_finalize)
1686                 mono_object_register_finalizer (res);
1687         return res;
1688 }
1689
1690 gpointer
1691 mono_object_unbox (MonoObject *obj)
1692 {
1693         /* add assert for valuetypes? */
1694         return ((char*)obj) + sizeof (MonoObject);
1695 }
1696
1697 /**
1698  * mono_object_isinst:
1699  * @obj: an object
1700  * @klass: a pointer to a class 
1701  *
1702  * Returns: @obj if @obj is derived from @klass
1703  */
1704 MonoObject *
1705 mono_object_isinst (MonoObject *obj, MonoClass *klass)
1706 {
1707         MonoVTable *vt;
1708         MonoClass *oklass;
1709
1710         if (!obj)
1711                 return NULL;
1712
1713         vt = obj->vtable;
1714         oklass = vt->klass;
1715
1716         if (!klass->inited)
1717                 mono_class_init (klass);
1718
1719         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1720                 if ((klass->interface_id <= vt->max_interface_id) &&
1721                     vt->interface_offsets [klass->interface_id])
1722                         return obj;
1723         } else {
1724                 if (oklass == mono_defaults.transparent_proxy_class) {
1725                         /* fixme: add check for IRemotingTypeInfo */
1726                         oklass = ((MonoTransparentProxy *)obj)->klass;
1727                 }
1728                 if (klass->rank) {
1729                         if (oklass->rank == klass->rank && mono_class_has_parent (oklass->cast_class, klass->cast_class))
1730                                 return obj;
1731                         
1732                 } else if (mono_class_has_parent (oklass, klass))
1733                         return obj;
1734         }
1735
1736         return NULL;
1737 }
1738
1739 typedef struct {
1740         MonoDomain *orig_domain;
1741         char *ins;
1742         MonoString *res;
1743 } LDStrInfo;
1744
1745 static void
1746 str_lookup (MonoDomain *domain, gpointer user_data)
1747 {
1748         LDStrInfo *info = user_data;
1749         if (info->res || domain == info->orig_domain)
1750                 return;
1751         mono_domain_lock (domain);
1752         info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
1753         mono_domain_unlock (domain);
1754 }
1755
1756 static MonoString*
1757 mono_string_is_interned_lookup (MonoString *str, int insert)
1758 {
1759         MonoGHashTable *ldstr_table;
1760         MonoString *res;
1761         MonoDomain *domain;
1762         char *ins = g_malloc (4 + str->length * 2);
1763         char *p;
1764         int bloblen;
1765         
1766         /* Encode the length */
1767         p = ins;
1768         mono_metadata_encode_value (2 * str->length, p, &p);
1769         bloblen = p - ins;
1770         p = ins;
1771         mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
1772         bloblen = (p - ins) + 2 * str->length;
1773         /*
1774          * ins is stored in the hash table as a key and needs to have the same
1775          * representation as in the metadata: we swap the character bytes on big
1776          * endian boxes.
1777          */
1778 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1779         {
1780                 int i;
1781                 char *p2 = mono_string_chars (str);
1782                 for (i = 0; i < str->length; ++i) {
1783                         *p++ = p2 [1];
1784                         *p++ = p2 [0];
1785                         p2 += 2;
1786                 }
1787         }
1788 #else
1789         memcpy (p, mono_string_chars (str), str->length * 2);
1790 #endif
1791         domain = ((MonoObject *)str)->vtable->domain;
1792         ldstr_table = domain->ldstr_table;
1793         mono_domain_lock (domain);
1794         if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1795                 mono_domain_unlock (domain);
1796                 g_free (ins);
1797                 return res;
1798         }
1799         if (insert) {
1800                 mono_g_hash_table_insert (ldstr_table, ins, str);
1801                 mono_domain_unlock (domain);
1802                 return str;
1803         } else {
1804                 LDStrInfo ldstr_info;
1805                 ldstr_info.orig_domain = domain;
1806                 ldstr_info.ins = ins;
1807                 ldstr_info.res = NULL;
1808
1809                 mono_domain_foreach (str_lookup, &ldstr_info);
1810                 if (ldstr_info.res) {
1811                         /* 
1812                          * the string was already interned in some other domain:
1813                          * intern it in the current one as well.
1814                          */
1815                         mono_g_hash_table_insert (ldstr_table, ins, str);
1816                         mono_domain_unlock (domain);
1817                         return str;
1818                 }
1819         }
1820         mono_domain_unlock (domain);
1821         g_free (ins);
1822         return NULL;
1823 }
1824
1825 MonoString*
1826 mono_string_is_interned (MonoString *o)
1827 {
1828         return mono_string_is_interned_lookup (o, FALSE);
1829 }
1830
1831 MonoString*
1832 mono_string_intern (MonoString *str)
1833 {
1834         return mono_string_is_interned_lookup (str, TRUE);
1835 }
1836
1837 /*
1838  * mono_ldstr:
1839  * @domain: the domain where the string will be used.
1840  * @image: a metadata context
1841  * @idx: index into the user string table.
1842  * 
1843  * Implementation for the ldstr opcode.
1844  */
1845 MonoString*
1846 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
1847 {
1848         const char *str, *sig;
1849         MonoString *o;
1850         size_t len2;
1851
1852         MONO_ARCH_SAVE_REGS;
1853
1854         if (image->assembly->dynamic)
1855                 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
1856         else
1857                 sig = str = mono_metadata_user_string (image, idx);
1858
1859         mono_domain_lock (domain);
1860         if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
1861                 mono_domain_unlock (domain);
1862                 return o;
1863         }
1864         
1865         len2 = mono_metadata_decode_blob_size (str, &str);
1866         len2 >>= 1;
1867
1868         o = mono_string_new_utf16 (domain, (guint16*)str, len2);
1869 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1870         {
1871                 int i;
1872                 guint16 *p2 = (guint16*)mono_string_chars (o);
1873                 for (i = 0; i < len2; ++i) {
1874                         *p2 = GUINT16_FROM_LE (*p2);
1875                         ++p2;
1876                 }
1877         }
1878 #endif
1879         mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
1880         mono_domain_unlock (domain);
1881
1882         return o;
1883 }
1884
1885 /*
1886  * mono_string_to_utf8:
1887  * @s: a System.String
1888  *
1889  * Return the UTF8 representation for @s.
1890  * the resulting buffer nedds to be freed with g_free().
1891  */
1892 char *
1893 mono_string_to_utf8 (MonoString *s)
1894 {
1895         char *as;
1896         GError *error = NULL;
1897
1898         if (s == NULL)
1899                 return NULL;
1900
1901         if (!s->length)
1902                 return g_strdup ("");
1903
1904         as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
1905         if (error) {
1906                 g_warning (error->message);
1907                 g_error_free (error);
1908         }
1909
1910         return as;
1911 }
1912
1913 /*
1914  * mono_string_to_utf16:
1915  * @s: a MonoString
1916  *
1917  * Return an null-terminated array of the utf-16 chars
1918  * contained in @s. The result must be freed with g_free().
1919  * This is a temporary helper until our string implementation
1920  * is reworked to always include the null terminating char.
1921  */
1922 gunichar2 *
1923 mono_string_to_utf16 (MonoString *s)
1924 {
1925         char *as;
1926
1927         if (s == NULL)
1928                 return NULL;
1929
1930         as = g_malloc ((s->length * 2) + 2);
1931         as [(s->length * 2)] = '\0';
1932         as [(s->length * 2) + 1] = '\0';
1933
1934         if (!s->length) {
1935                 return (gunichar2 *)(as);
1936         }
1937         
1938         memcpy (as, mono_string_chars(s), s->length * 2);
1939         return (gunichar2 *)(as);
1940 }
1941
1942 /*
1943  * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
1944  */
1945 MonoString *
1946 mono_string_from_utf16 (gunichar2 *data)
1947 {
1948         MonoDomain *domain = mono_domain_get ();
1949         int len = 0;
1950
1951         if (!data)
1952                 return NULL;
1953
1954         while (data [len]) len++;
1955
1956         return mono_string_new_utf16 (domain, data, len);
1957 }
1958
1959 G_GNUC_NORETURN static void
1960 default_ex_handler (MonoException *ex)
1961 {
1962         MonoObject *o = (MonoObject*)ex;
1963         g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
1964         exit (1);
1965 }
1966
1967 static G_GNUC_NORETURN MonoExceptionFunc ex_handler = default_ex_handler;
1968
1969 void
1970 mono_install_handler        (MonoExceptionFunc func)
1971 {
1972         ex_handler = func? func: default_ex_handler;
1973 }
1974
1975 /*
1976  * mono_raise_exception:
1977  * @ex: exception object
1978  *
1979  * Signal the runtime that the exception @ex has been raised in unmanaged code.
1980  */
1981 G_GNUC_NORETURN void
1982 mono_raise_exception (MonoException *ex) 
1983 {
1984         ex_handler (ex);
1985 }
1986
1987 MonoWaitHandle *
1988 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
1989 {
1990         MonoWaitHandle *res;
1991
1992         res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
1993
1994         res->handle = handle;
1995
1996         return res;
1997 }
1998
1999 MonoAsyncResult *
2000 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2001 {
2002         MonoAsyncResult *res;
2003
2004         res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2005
2006         res->data = data;
2007         res->async_state = state;
2008         res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
2009         res->sync_completed = FALSE;
2010         res->completed = FALSE;
2011
2012         return res;
2013 }
2014
2015 void
2016 mono_message_init (MonoDomain *domain,
2017                    MonoMethodMessage *this, 
2018                    MonoReflectionMethod *method,
2019                    MonoArray *out_args)
2020 {
2021         MonoMethodSignature *sig = method->method->signature;
2022         MonoString *name;
2023         int i, j;
2024         char **names;
2025         guint8 arg_type;
2026
2027         this->method = method;
2028
2029         this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2030         this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2031
2032         names = g_new (char *, sig->param_count);
2033         mono_method_get_param_names (method->method, (const char **) names);
2034         this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2035         
2036         for (i = 0; i < sig->param_count; i++) {
2037                  name = mono_string_new (domain, names [i]);
2038                  mono_array_set (this->names, gpointer, i, name);       
2039         }
2040
2041         g_free (names);
2042         
2043         for (i = 0, j = 0; i < sig->param_count; i++) {
2044
2045                 if (sig->params [i]->byref) {
2046                         if (out_args) {
2047                                 gpointer arg = mono_array_get (out_args, gpointer, j);
2048                                 mono_array_set (this->args, gpointer, i, arg);
2049                                 j++;
2050                         }
2051                         arg_type = 2;
2052                         if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
2053                                 arg_type |= 1;
2054                 } else {
2055                         arg_type = 1;
2056                 }
2057
2058                 mono_array_set (this->arg_types, guint8, i, arg_type);
2059         }
2060 }
2061
2062 /**
2063  * mono_remoting_invoke:
2064  * @real_proxy: pointer to a RealProxy object
2065  * @msg: The MonoMethodMessage to execute
2066  * @exc: used to store exceptions
2067  * @out_args: used to store output arguments
2068  *
2069  * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2070  * IMessage interface and it is not trivial to extract results from there. So
2071  * we call an helper method PrivateInvoke instead of calling
2072  * RealProxy::Invoke() directly.
2073  *
2074  * Returns: the result object.
2075  */
2076 MonoObject *
2077 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, 
2078                       MonoObject **exc, MonoArray **out_args)
2079 {
2080         MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2081         gpointer pa [4];
2082
2083         /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2084
2085         if (!im) {
2086                 MonoClass *klass;
2087                 int i;
2088
2089                 klass = mono_defaults.real_proxy_class; 
2090                        
2091                 for (i = 0; i < klass->method.count; ++i) {
2092                         if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2093                             klass->methods [i]->signature->param_count == 4) {
2094                                 im = klass->methods [i];
2095                                 break;
2096                         }
2097                 }
2098         
2099                 g_assert (im);
2100                 real_proxy->vtable->domain->private_invoke_method = im;
2101         }
2102
2103         pa [0] = real_proxy;
2104         pa [1] = msg;
2105         pa [2] = exc;
2106         pa [3] = out_args;
2107
2108         return mono_runtime_invoke (im, NULL, pa, exc);
2109 }
2110
2111 MonoObject *
2112 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, 
2113                      MonoObject **exc, MonoArray **out_args) 
2114 {
2115         MonoDomain *domain; 
2116         MonoMethod *method;
2117         MonoMethodSignature *sig;
2118         int i, j, outarg_count = 0;
2119
2120         if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2121
2122                 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2123                 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2124                         target = tp->rp->unwrapped_server;
2125                 } else {
2126                         return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2127                 }
2128         }
2129
2130         domain = mono_domain_get (); 
2131         method = msg->method->method;
2132         sig = method->signature;
2133
2134         for (i = 0; i < sig->param_count; i++) {
2135                 if (sig->params [i]->byref) 
2136                         outarg_count++;
2137         }
2138
2139         *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2140         *exc = NULL;
2141
2142         for (i = 0, j = 0; i < sig->param_count; i++) {
2143                 if (sig->params [i]->byref) {
2144                         gpointer arg;
2145                         arg = mono_array_get (msg->args, gpointer, i);
2146                         mono_array_set (*out_args, gpointer, j, arg);
2147                         j++;
2148                 }
2149         }
2150
2151         return mono_runtime_invoke_array (method, target, msg->args, exc);
2152 }
2153
2154 void
2155 mono_print_unhandled_exception (MonoObject *exc)
2156 {
2157         char *message = (char *) "";
2158         MonoString *str; 
2159         MonoMethod *method;
2160         MonoClass *klass;
2161         gboolean free_message = FALSE;
2162         gint i;
2163
2164         if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2165                 klass = exc->vtable->klass;
2166                 method = NULL;
2167                 while (klass && method == NULL) {
2168                         for (i = 0; i < klass->method.count; ++i) {
2169                                 method = klass->methods [i];
2170                                 if (!strcmp ("ToString", method->name) &&
2171                                     method->signature->param_count == 0 &&
2172                                     method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2173                                     method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2174                                         break;
2175                                 }
2176                                 method = NULL;
2177                         }
2178                         
2179                         if (method == NULL)
2180                                 klass = klass->parent;
2181                 }
2182
2183                 g_assert (method);
2184
2185                 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2186                 if (str) {
2187                         message = mono_string_to_utf8 (str);
2188                         free_message = TRUE;
2189                 }
2190         }                               
2191
2192         /*
2193          * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space, 
2194          *         exc->vtable->klass->name, message);
2195          */
2196         g_printerr ("\nUnhandled Exception: %s\n", message);
2197         
2198         if (free_message)
2199                 g_free (message);
2200 }
2201
2202 /**
2203  * mono_delegate_ctor:
2204  * @this: pointer to an uninitialized delegate object
2205  * @target: target object
2206  * @addr: pointer to native code
2207  *
2208  * This is used to initialize a delegate. We also insert the method_info if
2209  * we find the info with mono_jit_info_table_find().
2210  */
2211 void
2212 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2213 {
2214         MonoDomain *domain = mono_domain_get ();
2215         MonoDelegate *delegate = (MonoDelegate *)this;
2216         MonoMethod *method = NULL;
2217         MonoClass *class;
2218         MonoJitInfo *ji;
2219
2220         g_assert (this);
2221         g_assert (addr);
2222
2223         class = this->vtable->klass;
2224
2225         if ((ji = mono_jit_info_table_find (domain, addr))) {
2226                 method = ji->method;
2227                 delegate->method_info = mono_method_get_object (domain, method, NULL);
2228         }
2229
2230         if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2231                 g_assert (method);
2232                 method = mono_marshal_get_remoting_invoke (method);
2233                 delegate->method_ptr = mono_compile_method (method);
2234                 delegate->target = target;
2235         } else {
2236                 delegate->method_ptr = addr;
2237                 delegate->target = target;
2238         }
2239 }
2240
2241 /**
2242  * mono_method_call_message_new:
2243  *
2244  * Translates arguments pointers into a Message.
2245  */
2246 MonoMethodMessage *
2247 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke, 
2248                               MonoDelegate **cb, MonoObject **state)
2249 {
2250         MonoDomain *domain = mono_domain_get ();
2251         MonoMethodSignature *sig = method->signature;
2252         MonoMethodMessage *msg;
2253         int i, count, type;
2254
2255         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class); 
2256         
2257         if (invoke) {
2258                 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2259                 count =  sig->param_count - 2;
2260         } else {
2261                 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2262                 count =  sig->param_count;
2263         }
2264
2265         for (i = 0; i < count; i++) {
2266                 gpointer vpos;
2267                 MonoClass *class;
2268                 MonoObject *arg;
2269
2270                 if (sig->params [i]->byref)
2271                         vpos = *((gpointer *)params [i]);
2272                 else 
2273                         vpos = params [i];
2274
2275                 type = sig->params [i]->type;
2276                 class = mono_class_from_mono_type (sig->params [i]);
2277
2278                 if (class->valuetype)
2279                         arg = mono_value_box (domain, class, vpos);
2280                 else 
2281                         arg = *((MonoObject **)vpos);
2282                       
2283                 mono_array_set (msg->args, gpointer, i, arg);
2284         }
2285
2286         if (invoke) {
2287                 *cb = *((MonoDelegate **)params [i]);
2288                 i++;
2289                 *state = *((MonoObject **)params [i]);
2290         }
2291
2292         return msg;
2293 }
2294
2295 /**
2296  * mono_method_return_message_restore:
2297  *
2298  * Restore results from message based processing back to arguments pointers
2299  */
2300 void
2301 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2302 {
2303         MonoMethodSignature *sig = method->signature;
2304         int i, j, type, size;
2305         
2306         for (i = 0, j = 0; i < sig->param_count; i++) {
2307                 MonoType *pt = sig->params [i];
2308
2309                 size = mono_type_stack_size (pt, NULL);
2310
2311                 if (pt->byref) {
2312                         char *arg = mono_array_get (out_args, gpointer, j);
2313                         type = pt->type;
2314                         
2315                         switch (type) {
2316                         case MONO_TYPE_VOID:
2317                                 g_assert_not_reached ();
2318                                 break;
2319                         case MONO_TYPE_U1:
2320                         case MONO_TYPE_I1:
2321                         case MONO_TYPE_BOOLEAN:
2322                         case MONO_TYPE_U2:
2323                         case MONO_TYPE_I2:
2324                         case MONO_TYPE_CHAR:
2325                         case MONO_TYPE_U4:
2326                         case MONO_TYPE_I4:
2327                         case MONO_TYPE_I8:
2328                         case MONO_TYPE_U8:
2329                         case MONO_TYPE_R4:
2330                         case MONO_TYPE_R8:
2331                         case MONO_TYPE_VALUETYPE: {
2332                                 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size); 
2333                                 break;
2334                         }
2335                         case MONO_TYPE_STRING:
2336                         case MONO_TYPE_CLASS: 
2337                         case MONO_TYPE_ARRAY:
2338                         case MONO_TYPE_SZARRAY:
2339                                 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2340                                 break;
2341                         default:
2342                                 g_assert_not_reached ();
2343                         }
2344
2345                         j++;
2346                 }
2347         }
2348 }
2349
2350 /**
2351  * mono_load_remote_field:
2352  * @this: pointer to an object
2353  * @klass: klass of the object containing @field
2354  * @field: the field to load
2355  * @res: a storage to store the result
2356  *
2357  * This method is called by the runtime on attempts to load fields of
2358  * transparent proxy objects. @this points to such TP, @klass is the class of
2359  * the object containing @field. @res is a storage location which can be
2360  * used to store the result.
2361  *
2362  * Returns: an address pointing to the value of field.
2363  */
2364 gpointer
2365 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2366 {
2367         static MonoMethod *getter = NULL;
2368         MonoDomain *domain = mono_domain_get ();
2369         MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2370         MonoClass *field_class;
2371         MonoMethodMessage *msg;
2372         MonoArray *out_args;
2373         MonoObject *exc;
2374         gpointer tmp;
2375
2376         g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2377
2378         if (!res)
2379                 res = &tmp;
2380
2381         if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2382                 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2383                 return res;
2384         }
2385         
2386         if (!getter) {
2387                 int i;
2388
2389                 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2390                         MonoMethod *cm = mono_defaults.object_class->methods [i];
2391                
2392                         if (!strcmp (cm->name, "FieldGetter")) {
2393                                 getter = cm;
2394                                 break;
2395                         }
2396                 }
2397                 g_assert (getter);
2398         }
2399         
2400         field_class = mono_class_from_mono_type (field->type);
2401
2402         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2403         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2404         mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2405
2406         mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2407         mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2408
2409         mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2410
2411         *res = mono_array_get (out_args, MonoObject *, 0);
2412
2413         if (field_class->valuetype) {
2414                 return ((char *)*res) + sizeof (MonoObject);
2415         } else
2416                 return res;
2417 }
2418
2419 MonoObject *
2420 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2421 {
2422         static MonoMethod *getter = NULL;
2423         MonoDomain *domain = mono_domain_get ();
2424         MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2425         MonoClass *field_class;
2426         MonoMethodMessage *msg;
2427         MonoArray *out_args;
2428         MonoObject *exc, *res;
2429
2430         g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2431
2432         field_class = mono_class_from_mono_type (field->type);
2433
2434         if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2435                 gpointer val;
2436                 if (field_class->valuetype) {
2437                         res = mono_object_new (domain, field_class);
2438                         val = ((gchar *) res) + sizeof (MonoObject);
2439                 } else {
2440                         val = &res;
2441                 }
2442                 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2443                 return res;
2444         }
2445
2446         if (!getter) {
2447                 int i;
2448
2449                 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2450                         MonoMethod *cm = mono_defaults.object_class->methods [i];
2451                
2452                         if (!strcmp (cm->name, "FieldGetter")) {
2453                                 getter = cm;
2454                                 break;
2455                         }
2456                 }
2457                 g_assert (getter);
2458         }
2459         
2460         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2461         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2462         mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2463
2464         mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2465         mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2466
2467         mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2468
2469         res = mono_array_get (out_args, MonoObject *, 0);
2470
2471         return res;
2472 }
2473
2474 /**
2475  * mono_store_remote_field:
2476  * @this: pointer to an object
2477  * @klass: klass of the object containing @field
2478  * @field: the field to load
2479  * @val: the value/object to store
2480  *
2481  * This method is called by the runtime on attempts to store fields of
2482  * transparent proxy objects. @this points to such TP, @klass is the class of
2483  * the object containing @field. @val is the new value to store in @field.
2484  */
2485 void
2486 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
2487 {
2488         static MonoMethod *setter = NULL;
2489         MonoDomain *domain = mono_domain_get ();
2490         MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2491         MonoClass *field_class;
2492         MonoMethodMessage *msg;
2493         MonoArray *out_args;
2494         MonoObject *exc;
2495         MonoObject *arg;
2496
2497         g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2498
2499         field_class = mono_class_from_mono_type (field->type);
2500
2501         if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2502                 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
2503                 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
2504                 return;
2505         }
2506
2507         if (!setter) {
2508                 int i;
2509
2510                 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2511                         MonoMethod *cm = mono_defaults.object_class->methods [i];
2512                
2513                         if (!strcmp (cm->name, "FieldSetter")) {
2514                                 setter = cm;
2515                                 break;
2516                         }
2517                 }
2518                 g_assert (setter);
2519         }
2520
2521         if (field_class->valuetype)
2522                 arg = mono_value_box (domain, field_class, val);
2523         else 
2524                 arg = *((MonoObject **)val);
2525                 
2526
2527         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2528         mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2529
2530         mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2531         mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2532         mono_array_set (msg->args, gpointer, 2, arg);
2533
2534         mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2535 }
2536
2537 void
2538 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
2539 {
2540         static MonoMethod *setter = NULL;
2541         MonoDomain *domain = mono_domain_get ();
2542         MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2543         MonoClass *field_class;
2544         MonoMethodMessage *msg;
2545         MonoArray *out_args;
2546         MonoObject *exc;
2547
2548         g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2549
2550         field_class = mono_class_from_mono_type (field->type);
2551
2552         if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2553                 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
2554                 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
2555                 return;
2556         }
2557
2558         if (!setter) {
2559                 int i;
2560
2561                 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2562                         MonoMethod *cm = mono_defaults.object_class->methods [i];
2563                
2564                         if (!strcmp (cm->name, "FieldSetter")) {
2565                                 setter = cm;
2566                                 break;
2567                         }
2568                 }
2569                 g_assert (setter);
2570         }
2571
2572         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2573         mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2574
2575         mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2576         mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2577         mono_array_set (msg->args, gpointer, 2, arg);
2578
2579         mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2580 }
2581