Use start and end addresses for methods.
[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.h>
20 #include <mono/metadata/appdomain.h>
21 #include <mono/metadata/assembly.h>
22 #include <mono/metadata/threadpool.h>
23 #include <mono/metadata/marshal.h>
24 #include "mono/metadata/debug-helpers.h"
25 #include "mono/metadata/marshal.h"
26 #if HAVE_BOEHM_GC
27 #include <gc/gc.h>
28 #endif
29
30 void
31 mono_runtime_object_init (MonoObject *this)
32 {
33         int i;
34         MonoMethod *method = NULL;
35         MonoClass *klass = this->vtable->klass;
36
37         for (i = 0; i < klass->method.count; ++i) {
38                 if (!strcmp (".ctor", klass->methods [i]->name) &&
39                     klass->methods [i]->signature->param_count == 0) {
40                         method = klass->methods [i];
41                         break;
42                 }
43         }
44
45         g_assert (method);
46
47         mono_runtime_invoke (method, this, NULL, NULL);
48 }
49
50 /*
51  * runtime_class_init:
52  * @klass: klass that needs to be initialized
53  *
54  * This routine calls the class constructor for @class.
55  */
56 void
57 mono_runtime_class_init (MonoClass *klass)
58 {
59         int i;
60
61         for (i = 0; i < klass->method.count; ++i) {
62                 MonoMethod *method = klass->methods [i];
63                 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
64                     (strcmp (".cctor", method->name) == 0)) {
65                         mono_runtime_invoke (method, NULL, NULL, NULL);
66                         return;
67                 }
68         }
69
70         /* No class constructor found */
71 }
72
73 static gpointer
74 default_trampoline (MonoMethod *method)
75 {
76         return method;
77 }
78
79 static gpointer
80 default_remoting_trampoline (MonoMethod *method)
81 {
82         g_error ("remoting not installed");
83         return NULL;
84 }
85
86 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
87 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
88
89 void
90 mono_install_trampoline (MonoTrampoline func) 
91 {
92         arch_create_jit_trampoline = func? func: default_trampoline;
93 }
94
95 void
96 mono_install_remoting_trampoline (MonoTrampoline func) 
97 {
98         arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
99 }
100
101 static MonoCompileFunc default_mono_compile_method = NULL;
102
103 void        
104 mono_install_compile_method (MonoCompileFunc func)
105 {
106         default_mono_compile_method = func;
107 }
108
109 gpointer 
110 mono_compile_method (MonoMethod *method)
111 {
112         if (!default_mono_compile_method) {
113                 g_error ("compile method called on uninitialized runtime");
114                 return NULL;
115         }
116         return default_mono_compile_method (method);
117 }
118
119
120 #if 0 && HAVE_BOEHM_GC
121 static void
122 vtable_finalizer (void *obj, void *data) {
123         g_print ("%s finalized (%p)\n", (char*)data, obj);
124 }
125 #endif
126
127 /**
128  * mono_class_vtable:
129  * @domain: the application domain
130  * @class: the class to initialize
131  *
132  * VTables are domain specific because we create domain specific code, and 
133  * they contain the domain specific static class data.
134  */
135 MonoVTable *
136 mono_class_vtable (MonoDomain *domain, MonoClass *class)
137 {
138         MonoClass *k;
139         MonoVTable *vt;
140         MonoClassField *field;
141         guint32 cindex;
142         guint32 cols [MONO_CONSTANT_SIZE];
143         const char *p;
144         char *t;
145         int i, len;
146
147         g_assert (class);
148
149         vt = class->cached_vtable;
150         if (vt && vt->domain == domain)
151                 return vt;
152
153         /* can interfaces have static fields? */
154         if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
155                 g_assert_not_reached ();
156
157         mono_domain_lock (domain);
158         if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
159                 mono_domain_unlock (domain);
160                 return vt;
161         }
162         
163         if (!class->inited)
164                 mono_class_init (class);
165
166         mono_stats.used_class_count++;
167         mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
168
169         vt = mono_mempool_alloc0 (domain->mp,  sizeof (MonoVTable) + 
170                                   class->vtable_size * sizeof (gpointer));
171         vt->klass = class;
172         vt->domain = domain;
173
174         if (class->class_size) {
175 #if HAVE_BOEHM_GC
176                 vt->data = GC_malloc (class->class_size + 8);
177                 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
178                 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
179                 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
180 #else
181                 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
182                 
183 #endif
184                 mono_stats.class_static_data_size += class->class_size + 8;
185         }
186
187         for (i = class->field.first; i < class->field.last; ++i) {
188                 field = &class->fields [i - class->field.first];
189                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
190                         continue;
191                 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
192                         MonoClass *fklass = mono_class_from_mono_type (field->type);
193                         t = (char*)vt->data + field->offset;
194                         g_assert (fklass->valuetype);
195                         memcpy (t, field->data, mono_class_value_size (fklass, NULL));
196                         continue;
197                 }
198                 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
199                         continue;
200                 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1));
201                 if (!cindex) {
202                         g_warning ("constant for field %s not found", field->name);
203                         continue;
204                 }
205                 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE);
206                 p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]);
207                 len = mono_metadata_decode_blob_size (p, &p);
208                 t = (char*)vt->data + field->offset;
209                 /* should we check that the type matches? */
210                 switch (cols [MONO_CONSTANT_TYPE]) {
211                 case MONO_TYPE_BOOLEAN:
212                 case MONO_TYPE_U1:
213                 case MONO_TYPE_I1:
214                         *t = *p;
215                         break;
216                 case MONO_TYPE_CHAR:
217                 case MONO_TYPE_U2:
218                 case MONO_TYPE_I2: {
219                         guint16 *val = (guint16*)t;
220                         *val = read16 (p);
221                         break;
222                 }
223                 case MONO_TYPE_U4:
224                 case MONO_TYPE_I4: {
225                         guint32 *val = (guint32*)t;
226                         *val = read32 (p);
227                         break;
228                 }
229                 case MONO_TYPE_U8:
230                 case MONO_TYPE_I8: {
231                         guint64 *val = (guint64*)t;
232                         *val = read64 (p);
233                         break;
234                 }
235                 case MONO_TYPE_R4: {
236                         float *val = (float*)t;
237                         readr4 (p, val);
238                         break;
239                 }
240                 case MONO_TYPE_R8: {
241                         double *val = (double*)t;
242                         readr8 (p, val);
243                         break;
244                 }
245                 case MONO_TYPE_STRING: {
246                         gpointer *val = (gpointer*)t;
247 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
248                         gunichar2 *copy = g_malloc (len);
249                         int j;
250                         for (j = 0; j < len/2; j++) {
251                                 copy [j] = read16 (p);
252                                 p += 2;
253                         }
254                         *val = mono_string_new_utf16 (domain, copy, len/2);
255                         g_free (copy);
256 #else
257                         *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
258 #endif
259                         break;
260                 }
261                 case MONO_TYPE_CLASS:
262                         /* nothing to do, we malloc0 the data and the value can be 0 only */
263                         break;
264                 default:
265                         g_warning ("type 0x%02x should not be in constant table", cols [MONO_CONSTANT_TYPE]);
266                 }
267         }
268
269         vt->max_interface_id = class->max_interface_id;
270         
271         vt->interface_offsets = mono_mempool_alloc0 (domain->mp, 
272                 sizeof (gpointer) * (class->max_interface_id + 1));
273
274         /* initialize interface offsets */
275         for (k = class; k ; k = k->parent) {
276                 for (i = 0; i < k->interface_count; i++) {
277                         int slot;
278                         MonoClass *ic = k->interfaces [i];
279                         slot = class->interface_offsets [ic->interface_id];
280                         vt->interface_offsets [ic->interface_id] = &vt->vtable [slot];
281                 }
282         }
283
284         /* initialize vtable */
285         for (i = 0; i < class->vtable_size; ++i) {
286                 MonoMethod *cm;
287                
288                 if ((cm = class->vtable [i]))
289                         vt->vtable [i] = arch_create_jit_trampoline (cm);
290         }
291
292         mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
293         if (!class->cached_vtable)
294                 class->cached_vtable = vt;
295
296         mono_domain_unlock (domain);
297
298         /* make sure the the parent is initialized */
299         if (class->parent)
300                 mono_class_vtable (domain, class->parent);
301
302         mono_runtime_class_init (class);
303         
304         return vt;
305 }
306
307 /**
308  * mono_class_proxy_vtable:
309  * @domain: the application domain
310  * @class: the class to proxy
311  *
312  * Creates a vtable for transparent proxies. It is basically
313  * a copy of the real vtable of @class, but all function pointers invoke
314  * the remoting functions, and vtable->klass points to the 
315  * transparent proxy class, and not to @class.
316  */
317 MonoVTable *
318 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
319 {
320         MonoVTable *vt, *pvt;
321         int i, vtsize;
322
323         if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
324                 return pvt;
325
326         vt = mono_class_vtable (domain, class);
327         vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
328
329         mono_stats.class_vtable_size += vtsize;
330
331         pvt = mono_mempool_alloc (domain->mp, vtsize);
332         memcpy (pvt, vt, vtsize);
333
334         pvt->klass = mono_defaults.transparent_proxy_class;
335
336         /* initialize vtable */
337         for (i = 0; i < class->vtable_size; ++i) {
338                 MonoMethod *cm;
339                
340                 if ((cm = class->vtable [i]))
341                         pvt->vtable [i] = arch_create_remoting_trampoline (cm);
342         }
343
344         mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
345
346         return pvt;
347 }
348
349 static MonoInvokeFunc default_mono_runtime_invoke = NULL;
350
351 MonoObject*
352 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
353 {
354         if (!default_mono_runtime_invoke) {
355                 g_error ("runtime invoke called on uninitialized runtime");
356                 return NULL;
357         }
358
359         return default_mono_runtime_invoke (method, obj, params, exc);
360 }
361
362 static void
363 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
364         int t;
365         if (type->byref) {
366                 gpointer *p = (gpointer*)dest;
367                 *p = value;
368                 return;
369         }
370         t = type->type;
371 handle_enum:
372         switch (t) {
373         case MONO_TYPE_BOOLEAN:
374         case MONO_TYPE_I1:
375         case MONO_TYPE_U1: {
376                 guint8 *p = (guint8*)dest;
377                 *p = *(guint8*)value;
378                 return;
379         }
380         case MONO_TYPE_I2:
381         case MONO_TYPE_U2:
382         case MONO_TYPE_CHAR: {
383                 guint16 *p = (guint16*)dest;
384                 *p = *(guint16*)value;
385                 return;
386         }
387 #if SIZEOF_VOID_P == 4
388         case MONO_TYPE_I:
389         case MONO_TYPE_U:
390 #endif
391         case MONO_TYPE_I4:
392         case MONO_TYPE_U4: {
393                 gint32 *p = (gint32*)dest;
394                 *p = *(gint32*)value;
395                 return;
396         }
397 #if SIZEOF_VOID_P == 8
398         case MONO_TYPE_I:
399         case MONO_TYPE_U:
400 #endif
401         case MONO_TYPE_I8:
402         case MONO_TYPE_U8: {
403                 gint64 *p = (gint64*)dest;
404                 *p = *(gint64*)value;
405                 return;
406         }
407         case MONO_TYPE_R4: {
408                 float *p = (float*)dest;
409                 *p = *(float*)value;
410                 return;
411         }
412         case MONO_TYPE_R8: {
413                 double *p = (double*)dest;
414                 *p = *(double*)value;
415                 return;
416         }
417         case MONO_TYPE_STRING:
418         case MONO_TYPE_SZARRAY:
419         case MONO_TYPE_CLASS:
420         case MONO_TYPE_OBJECT:
421         case MONO_TYPE_ARRAY:
422         case MONO_TYPE_PTR: {
423                 gpointer *p = (gpointer*)dest;
424                 *p = deref_pointer? *(gpointer*)value: value;
425                 return;
426         }
427         case MONO_TYPE_VALUETYPE:
428                 if (type->data.klass->enumtype) {
429                         t = type->data.klass->enum_basetype->type;
430                         goto handle_enum;
431                 } else {
432                         int size;
433                         size = mono_class_value_size (type->data.klass, NULL);
434                         memcpy (dest, value, size);
435                 }
436                 return;
437         default:
438                 g_warning ("got type %x", type->type);
439                 g_assert_not_reached ();
440         }
441 }
442
443 void
444 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
445 {
446         void *dest;
447
448         g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
449
450         dest = (char*)obj + field->offset;
451         set_value (field->type, dest, value, FALSE);
452 }
453
454 void
455 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
456 {
457         void *dest;
458
459         g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
460
461         dest = (char*)vt->data + field->offset;
462         set_value (field->type, dest, value, FALSE);
463 }
464
465 void
466 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
467 {
468         void *src;
469
470         g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
471
472         src = (char*)obj + field->offset;
473         set_value (field->type, value, src, TRUE);
474 }
475
476 void
477 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
478 {
479         void *src;
480
481         g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
482
483         src = (char*)vt->data + field->offset;
484         set_value (field->type, value, src, TRUE);
485 }
486
487 void
488 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
489 {
490         default_mono_runtime_invoke (prop->set, obj, params, exc);
491 }
492
493 MonoObject*
494 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
495 {
496         return default_mono_runtime_invoke (prop->get, obj, params, exc);
497 }
498
499
500 MonoMethod *
501 mono_get_delegate_invoke (MonoClass *klass)
502 {
503         MonoMethod *im;
504         int i;
505
506         im = NULL;
507
508         for (i = 0; i < klass->method.count; ++i) {
509                 if (klass->methods [i]->name[0] == 'I' && 
510                     !strcmp ("Invoke", klass->methods [i]->name)) {
511                         im = klass->methods [i];
512                 }
513         }
514
515         g_assert (im);
516
517         return im;
518 }
519
520 MonoObject*
521 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
522 {
523         MonoMethod *im;
524
525         im = mono_get_delegate_invoke (delegate->vtable->klass);
526         g_assert (im);
527
528         return mono_runtime_invoke (im, delegate, params, exc);
529 }
530
531 static MonoArray* main_args;
532
533 MonoArray*
534 mono_runtime_get_main_args (void)
535 {
536         return main_args;
537 }
538
539 MonoMethod *mono_start_method = NULL;
540
541 /*
542  * Execute a standard Main() method (argc/argv contains the
543  * executable name). This method also sets the command line argument value
544  * needed by System.Environment.
545  */
546 int
547 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
548                        MonoObject **exc)
549 {
550         int i;
551         MonoArray *args = NULL;
552         MonoDomain *domain = mono_domain_get ();
553
554         main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
555         for (i = 0; i < argc; ++i) {
556                 MonoString *arg = mono_string_new (domain, argv [i]);
557                 mono_array_set (main_args, gpointer, i, arg);
558         }
559         argc--;
560         argv++;
561         if (method->signature->param_count) {
562                 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
563                 for (i = 0; i < argc; ++i) {
564                         MonoString *arg = mono_string_new (domain, argv [i]);
565                         mono_array_set (args, gpointer, i, arg);
566                 }
567         } else {
568                 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
569         }
570         
571         mono_assembly_set_main (method->klass->image->assembly);
572
573         mono_start_method = mono_marshal_get_runtime_invoke (method);
574         
575         return mono_runtime_exec_main (method, args, exc);
576 }
577
578 /*
579  * We call this function when we dectect an unhandled exception. It invokes the
580  * UnhandledException event in AppDomain or print a warning to the console 
581  */
582 void
583 mono_unhandled_exception (MonoObject *exc)
584 {
585         MonoDomain *domain = mono_domain_get ();
586         MonoClassField *field;
587         MonoObject *delegate;
588         
589         field=mono_class_get_field_from_name(mono_defaults.appdomain_class, 
590                                              "UnhandledException");
591         g_assert (field);
592
593         if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
594                 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset); 
595
596                 if (!delegate) {
597                         mono_print_unhandled_exception (exc);
598                 } else {
599                         MonoObject *e = NULL;
600                         gpointer pa [2];
601
602                         /* fixme: pass useful arguments */
603                         pa [0] = NULL;
604                         pa [1] = NULL;
605                         mono_runtime_delegate_invoke (delegate, pa, &e);
606                         
607                         if (e)
608                                 g_warning ("exception inside UnhandledException handler!");
609                 }
610         }
611 }
612
613 /*
614  * Execute a standard Main() method (args doesn't contain the
615  * executable name).
616  */
617 int
618 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
619 {
620         MonoDomain *domain;
621         gpointer pa [1];
622         int rval;
623
624         g_assert (args);
625
626         pa [0] = args;
627
628         domain = mono_object_domain (args);
629         if (!domain->entry_assembly)
630                 domain->entry_assembly = method->klass->image->assembly;
631
632         /* FIXME: check signature of method */
633         if (method->signature->ret->type == MONO_TYPE_I4) {
634                 MonoObject *res;
635                 res = mono_runtime_invoke (method, NULL, pa, exc);
636                 if (!exc || !*exc)
637                         rval = *(guint32 *)((char *)res + sizeof (MonoObject));
638                 else
639                         rval = -1;
640         } else {
641                 mono_runtime_invoke (method, NULL, pa, exc);
642                 if (!exc || !*exc)
643                         rval = 0;
644                 else
645                         rval = -1;
646         }
647
648         return rval;
649 }
650
651 void
652 mono_install_runtime_invoke (MonoInvokeFunc func)
653 {
654         default_mono_runtime_invoke = func;
655 }
656
657 MonoObject*
658 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
659                            MonoObject **exc)
660 {
661         MonoMethodSignature *sig = method->signature;
662         gpointer *pa = NULL;
663         int i;
664                 
665         if (NULL != params) {
666                 pa = alloca (sizeof (gpointer) * mono_array_length (params));
667                 for (i = 0; i < mono_array_length (params); i++) {
668                         if (sig->params [i]->byref) {
669                                 /* nothing to do */
670                         }
671
672                         switch (sig->params [i]->type) {
673                         case MONO_TYPE_U1:
674                         case MONO_TYPE_I1:
675                         case MONO_TYPE_BOOLEAN:
676                         case MONO_TYPE_U2:
677                         case MONO_TYPE_I2:
678                         case MONO_TYPE_CHAR:
679                         case MONO_TYPE_U:
680                         case MONO_TYPE_I:
681                         case MONO_TYPE_U4:
682                         case MONO_TYPE_I4:
683                         case MONO_TYPE_U8:
684                         case MONO_TYPE_I8:
685                         case MONO_TYPE_VALUETYPE:
686                                 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
687                                 break;
688                         case MONO_TYPE_STRING:
689                         case MONO_TYPE_OBJECT:
690                         case MONO_TYPE_CLASS:
691                         case MONO_TYPE_ARRAY:
692                         case MONO_TYPE_SZARRAY:
693                                 pa [i] = (char *)(((gpointer *)params->vector)[i]);
694                                 break;
695                         default:
696                                 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
697                         }
698                 }
699         }
700
701         if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
702                 obj = mono_object_new (mono_domain_get (), method->klass);
703                 mono_runtime_invoke (method, obj, pa, exc);
704                 return obj;
705         } else
706                 return mono_runtime_invoke (method, obj, pa, exc);
707 }
708
709 /**
710  * mono_object_allocate:
711  * @size: number of bytes to allocate
712  *
713  * This is a very simplistic routine until we have our GC-aware
714  * memory allocator. 
715  *
716  * Returns: an allocated object of size @size, or NULL on failure.
717  */
718 void *
719 mono_object_allocate (size_t size)
720 {
721 #if HAVE_BOEHM_GC
722         /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
723         void *o = GC_malloc (size);
724 #else
725         void *o = calloc (1, size);
726 #endif
727
728         return o;
729 }
730
731 /**
732  * mono_object_free:
733  *
734  * Frees the memory used by the object.  Debugging purposes
735  * only, as we will have our GC system.
736  */
737 void
738 mono_object_free (MonoObject *o)
739 {
740 #if HAVE_BOEHM_GC
741         g_error ("mono_object_free called with boehm gc.");
742 #else
743         MonoClass *c = o->vtable->klass;
744         
745         memset (o, 0, c->instance_size);
746         free (o);
747 #endif
748 }
749
750 /**
751  * mono_object_new:
752  * @klass: the class of the object that we want to create
753  *
754  * Returns: A newly created object whose definition is
755  * looked up using @klass
756  */
757 MonoObject *
758 mono_object_new (MonoDomain *domain, MonoClass *klass)
759 {
760         return mono_object_new_specific (mono_class_vtable (domain, klass));
761 }
762
763 /**
764  * mono_object_new_specific:
765  * @vtable: the vtable of the object that we want to create
766  *
767  * Returns: A newly created object with class and domain specified
768  * by @vtable
769  */
770 MonoObject *
771 mono_object_new_specific (MonoVTable *vtable)
772 {
773         MonoObject *o;
774
775         mono_stats.new_object_count++;
776
777         o = mono_object_allocate (vtable->klass->instance_size);
778         o->vtable = vtable;
779         if (vtable->klass->has_finalize)
780                 mono_object_register_finalizer (o);
781         
782         return o;
783 }
784
785 /**
786  * mono_object_new_from_token:
787  * @image: Context where the type_token is hosted
788  * @token: a token of the type that we want to create
789  *
790  * Returns: A newly created object whose definition is
791  * looked up using @token in the @image image
792  */
793 MonoObject *
794 mono_object_new_from_token  (MonoDomain *domain, MonoImage *image, guint32 token)
795 {
796         MonoClass *class;
797
798         class = mono_class_get (image, token);
799
800         return mono_object_new (domain, class);
801 }
802
803
804 /**
805  * mono_object_clone:
806  * @obj: the object to clone
807  *
808  * Returns: A newly created object who is a shallow copy of @obj
809  */
810 MonoObject *
811 mono_object_clone (MonoObject *obj)
812 {
813         MonoObject *o;
814         int size;
815
816         size = obj->vtable->klass->instance_size;
817         o = mono_object_allocate (size);
818
819         memcpy (o, obj, size);
820
821         if (obj->vtable->klass->has_finalize)
822                 mono_object_register_finalizer (o);
823         return o;
824 }
825
826 /**
827  * mono_array_clone:
828  * @array: the array to clone
829  *
830  * Returns: A newly created array who is a shallow copy of @array
831  */
832 MonoArray*
833 mono_array_clone (MonoArray *array)
834 {
835         MonoArray *o;
836         int size, i;
837         guint32 *sizes;
838         MonoClass *klass = array->obj.vtable->klass;
839
840         if (array->bounds == NULL) {
841                 size = mono_array_length (array);
842                 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
843                                          klass, &size, NULL);
844
845                 size *= mono_array_element_size (klass);
846                 memcpy (o, array, sizeof (MonoArray) + size);
847
848                 return o;
849         }
850         
851         sizes = alloca (klass->rank * sizeof(guint32) * 2);
852         size = mono_array_element_size (klass);
853         for (i = 0; i < klass->rank; ++i) {
854                 sizes [i] = array->bounds [i].length;
855                 size *= array->bounds [i].length;
856                 sizes [i + klass->rank] = array->bounds [i].lower_bound;
857         }
858         o = mono_array_new_full (((MonoObject *)array)->vtable->domain, 
859                                  klass, sizes, sizes + klass->rank);
860         memcpy (o, array, sizeof(MonoArray) + size);
861
862         return o;
863 }
864
865 /*
866  * mono_array_new_full:
867  * @domain: domain where the object is created
868  * @array_class: array class
869  * @lengths: lengths for each dimension in the array
870  * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
871  *
872  * This routine creates a new array objects with the given dimensions,
873  * lower bounds and type.
874  */
875 MonoArray*
876 mono_array_new_full (MonoDomain *domain, MonoClass *array_class, 
877                      guint32 *lengths, guint32 *lower_bounds)
878 {
879         guint32 byte_len, len;
880         MonoObject *o;
881         MonoArray *array;
882         MonoArrayBounds *bounds;
883         int i;
884
885         if (!array_class->inited)
886                 mono_class_init (array_class);
887
888         byte_len = mono_array_element_size (array_class);
889         len = 1;
890
891         if (array_class->rank == 1 &&
892             (lower_bounds == NULL || lower_bounds [0] == 0)) {
893                 bounds = NULL;
894                 len = lengths [0];
895         } else {
896         #if HAVE_BOEHM_GC
897                 bounds = GC_malloc (sizeof (MonoArrayBounds) * array_class->rank);
898         #else
899                 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
900         #endif
901                 for (i = 0; i < array_class->rank; ++i) {
902                         bounds [i].length = lengths [i];
903                         len *= lengths [i];
904                 }
905
906                 if (lower_bounds)
907                         for (i = 0; i < array_class->rank; ++i)
908                                 bounds [i].lower_bound = lower_bounds [i];
909         }
910
911         byte_len *= len;
912         /* 
913          * Following three lines almost taken from mono_object_new ():
914          * they need to be kept in sync.
915          */
916         o = mono_object_allocate (sizeof (MonoArray) + byte_len);
917         if (!o)
918                 G_BREAKPOINT ();
919         o->vtable = mono_class_vtable (domain, array_class);
920
921         array = (MonoArray*)o;
922
923         array->bounds = bounds;
924         array->max_length = len;
925
926         return array;
927 }
928
929 /*
930  * mono_array_new:
931  * @domain: domain where the object is created
932  * @eclass: element class
933  * @n: number of array elements
934  *
935  * This routine creates a new szarray with @n elements of type @eclass.
936  */
937 MonoArray *
938 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
939 {
940         MonoClass *ac;
941
942         ac = mono_array_class_get (&eclass->byval_arg, 1);
943         g_assert (ac != NULL);
944
945         return mono_array_new_specific (mono_class_vtable (domain, ac), n);
946 }
947
948 /*
949  * mono_array_new_specific:
950  * @vtable: a vtable in the appropriate domain for an initialized class
951  * @n: number of array elements
952  *
953  * This routine is a fast alternative to mono_array_new() for code which
954  * can be sure about the domain it operates in.
955  */
956 MonoArray *
957 mono_array_new_specific (MonoVTable *vtable, guint32 n)
958 {
959         MonoObject *o;
960         MonoArray *ao;
961         gsize byte_len;
962
963         byte_len = n * mono_array_element_size (vtable->klass);
964         o = mono_object_allocate (sizeof (MonoArray) + byte_len);
965         if (!o)
966                 G_BREAKPOINT ();
967         o->vtable = vtable;
968
969         ao = (MonoArray *)o;
970         ao->bounds = NULL;
971         ao->max_length = n;
972
973         return ao;
974 }
975
976 /**
977  * mono_string_new_utf16:
978  * @text: a pointer to an utf16 string
979  * @len: the length of the string
980  *
981  * Returns: A newly created string object which contains @text.
982  */
983 MonoString *
984 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
985 {
986         MonoString *s;
987         
988         s = mono_string_new_size (domain, len);
989         g_assert (s != NULL);
990
991         memcpy (mono_string_chars (s), text, len * 2);
992
993         return s;
994 }
995
996 /**
997  * mono_string_new_size:
998  * @text: a pointer to an utf16 string
999  * @len: the length of the string
1000  *
1001  * Returns: A newly created string object of @len
1002  */
1003 MonoString *
1004 mono_string_new_size (MonoDomain *domain, gint32 len)
1005 {
1006         MonoString *s;
1007
1008         /* 
1009          * enable to get a good speedup: we still need to figure out
1010          * how the sync structure is freed.
1011          */
1012 #if 0
1013         s = GC_malloc_atomic (sizeof (MonoString) + ((len + 1) * 2));
1014         s->object.synchronisation = 0;
1015         mono_string_chars (s) [len] = 0;
1016 #else
1017         s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1018 #endif
1019         if (!s)
1020                 G_BREAKPOINT ();
1021
1022         s->object.vtable = mono_class_vtable (domain, mono_defaults.string_class);
1023         s->length = len;
1024
1025         return s;
1026 }
1027
1028 /*
1029  * mono_string_new_len:
1030  * @text: a pointer to an utf8 string
1031  * @length: number of bytes in @text to consider
1032  *
1033  * Returns: A newly created string object which contains @text.
1034  */
1035 MonoString*
1036 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1037 {
1038         GError *error = NULL;
1039         MonoString *o = NULL;
1040         guint16 *ut;
1041         glong items_written;
1042
1043         
1044         ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1045
1046         if (!error)
1047                 o = mono_string_new_utf16 (domain, ut, items_written);
1048         else 
1049                 g_error_free (error);
1050
1051         g_free (ut);
1052
1053         return o;
1054 }
1055
1056 /**
1057  * mono_string_new:
1058  * @text: a pointer to an utf8 string
1059  *
1060  * Returns: A newly created string object which contains @text.
1061  */
1062 MonoString*
1063 mono_string_new (MonoDomain *domain, const char *text)
1064 {
1065         GError *error = NULL;
1066         MonoString *o = NULL;
1067         guint16 *ut;
1068         glong items_written;
1069         int l;
1070
1071         l = strlen (text);
1072         
1073         ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1074
1075         if (!error)
1076                 o = mono_string_new_utf16 (domain, ut, items_written);
1077         else 
1078                 g_error_free (error);
1079
1080         g_free (ut);
1081
1082         return o;
1083 }
1084
1085 /*
1086  * mono_string_new_wrapper:
1087  * @text: pointer to utf8 characters.
1088  *
1089  * Helper function to create a string object from @text in the current domain.
1090  */
1091 MonoString*
1092 mono_string_new_wrapper (const char *text)
1093 {
1094         MonoDomain *domain = mono_domain_get ();
1095
1096         if (text)
1097                 return mono_string_new (domain, text);
1098
1099         return NULL;
1100 }
1101
1102 /**
1103  * mono_value_box:
1104  * @class: the class of the value
1105  * @value: a pointer to the unboxed data
1106  *
1107  * Returns: A newly created object which contains @value.
1108  */
1109 MonoObject *
1110 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1111 {
1112         MonoObject *res;
1113         int size;
1114
1115         g_assert (class->valuetype);
1116
1117         size = mono_class_instance_size (class);
1118         res = mono_object_allocate (size);
1119         res->vtable = mono_class_vtable (domain, class);
1120
1121         size = size - sizeof (MonoObject);
1122
1123 #if NO_UNALIGNED_ACCESS
1124         memcpy ((char *)res + sizeof (MonoObject), value, size);
1125 #else
1126         switch (size) {
1127         case 1:
1128                 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
1129                 break;
1130         case 2:
1131                 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
1132                 break;
1133         case 4:
1134                 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
1135                 break;
1136         case 8:
1137                 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
1138                 break;
1139         default:
1140                 memcpy ((char *)res + sizeof (MonoObject), value, size);
1141         }
1142 #endif
1143         if (class->has_finalize)
1144                 mono_object_register_finalizer (res);
1145         return res;
1146 }
1147
1148 /**
1149  * mono_object_isinst:
1150  * @obj: an object
1151  * @klass: a pointer to a class 
1152  *
1153  * Returns: @obj if @obj is derived from @klass
1154  */
1155 MonoObject *
1156 mono_object_isinst (MonoObject *obj, MonoClass *klass)
1157 {
1158         MonoVTable *vt;
1159         MonoClass *oklass;
1160
1161         if (!obj)
1162                 return NULL;
1163
1164         vt = obj->vtable;
1165         oklass = vt->klass;
1166
1167         if (!klass->inited)
1168                 mono_class_init (klass);
1169
1170         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1171                 if ((klass->interface_id <= oklass->max_interface_id) &&
1172                     vt->interface_offsets [klass->interface_id])
1173                         return obj;
1174         } else {
1175                 if (oklass == mono_defaults.transparent_proxy_class) {
1176                         /* fixme: add check for IRemotingTypeInfo */
1177                         oklass = ((MonoTransparentProxy *)obj)->klass;
1178                 }
1179                 if (klass->rank) {
1180                         if (oklass->rank == klass->rank && 
1181                             (oklass->element_class->baseval - klass->element_class->baseval) <= 
1182                             klass->element_class->diffval)
1183                                 return obj;
1184                         
1185                 } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
1186                         return obj;
1187         }
1188
1189         return NULL;
1190 }
1191
1192 static MonoString*
1193 mono_string_is_interned_lookup (MonoString *str, int insert)
1194 {
1195         MonoGHashTable *ldstr_table;
1196         MonoString *res;
1197         MonoDomain *domain;
1198         char *ins = g_malloc (4 + str->length * 2);
1199         char *p;
1200         int bloblen;
1201         
1202         /* Encode the length */
1203         p = ins;
1204         mono_metadata_encode_value (2 * str->length, p, &p);
1205         bloblen = p - ins;
1206         p = ins;
1207         mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
1208         bloblen = (p - ins) + 2 * str->length;
1209         /*
1210          * ins is stored in the hash table as a key and needs to have the same
1211          * representation as in the metadata: we swap the character bytes on big
1212          * endian boxes.
1213          */
1214 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1215         {
1216                 int i;
1217                 char *p2 = mono_string_chars (str);
1218                 for (i = 0; i < str->length; ++i) {
1219                         *p++ = p2 [1];
1220                         *p++ = p2 [0];
1221                         p2 += 2;
1222                 }
1223         }
1224 #else
1225         memcpy (p, mono_string_chars (str), str->length * 2);
1226 #endif
1227         domain = ((MonoObject *)str)->vtable->domain;
1228         ldstr_table = domain->ldstr_table;
1229         mono_domain_lock (domain);
1230         if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1231                 mono_domain_unlock (domain);
1232                 g_free (ins);
1233                 return res;
1234         }
1235         if (insert) {
1236                 mono_g_hash_table_insert (ldstr_table, ins, str);
1237                 mono_domain_unlock (domain);
1238                 return str;
1239         }
1240         mono_domain_unlock (domain);
1241         g_free (ins);
1242         return NULL;
1243 }
1244
1245 MonoString*
1246 mono_string_is_interned (MonoString *o)
1247 {
1248         return mono_string_is_interned_lookup (o, FALSE);
1249 }
1250
1251 MonoString*
1252 mono_string_intern (MonoString *str)
1253 {
1254         return mono_string_is_interned_lookup (str, TRUE);
1255 }
1256
1257 /*
1258  * mono_ldstr:
1259  * @domain: the domain where the string will be used.
1260  * @image: a metadata context
1261  * @idx: index into the user string table.
1262  * 
1263  * Implementation for the ldstr opcode.
1264  */
1265 MonoString*
1266 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
1267 {
1268         const char *str, *sig;
1269         MonoString *o;
1270         size_t len2;
1271                 
1272         sig = str = mono_metadata_user_string (image, idx);
1273
1274         mono_domain_lock (domain);
1275         if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
1276                 mono_domain_unlock (domain);
1277                 return o;
1278         }
1279         
1280         len2 = mono_metadata_decode_blob_size (str, &str);
1281         len2 >>= 1;
1282
1283         o = mono_string_new_utf16 (domain, (guint16*)str, len2);
1284 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1285         {
1286                 int i;
1287                 guint16 *p2 = (guint16*)mono_string_chars (o);
1288                 for (i = 0; i < len2; ++i) {
1289                         *p2 = GUINT16_FROM_LE (*p2);
1290                         ++p2;
1291                 }
1292         }
1293 #endif
1294         mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
1295         mono_domain_unlock (domain);
1296
1297         return o;
1298 }
1299
1300 /*
1301  * mono_string_to_utf8:
1302  * @s: a System.String
1303  *
1304  * Return the UTF8 representation for @s.
1305  * the resulting buffer nedds to be freed with g_free().
1306  */
1307 char *
1308 mono_string_to_utf8 (MonoString *s)
1309 {
1310         char *as;
1311         GError *error = NULL;
1312
1313         if (s == NULL)
1314                 return NULL;
1315
1316         if (!s->length)
1317                 return g_strdup ("");
1318
1319         as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
1320         if (error)
1321                 g_warning (error->message);
1322
1323         return as;
1324 }
1325
1326 /*
1327  * mono_string_to_utf16:
1328  * @s: a MonoString
1329  *
1330  * Return an null-terminated array of the utf-16 chars
1331  * contained in @s. The result must be freed with g_free().
1332  * This is a temporary helper until our string implementation
1333  * is reworked to always include the null terminating char.
1334  */
1335 gunichar2 *
1336 mono_string_to_utf16 (MonoString *s)
1337 {
1338         char *as;
1339
1340         if (s == NULL)
1341                 return NULL;
1342
1343         as = g_malloc ((s->length * 2) + 2);
1344         as [(s->length * 2)] = '\0';
1345         as [(s->length * 2) + 1] = '\0';
1346
1347         if (!s->length) {
1348                 return (gunichar2 *)(as);
1349         }
1350         
1351         memcpy (as, mono_string_chars(s), s->length * 2);
1352         return (gunichar2 *)(as);
1353 }
1354
1355 static void
1356 default_ex_handler (MonoException *ex)
1357 {
1358         MonoObject *o = (MonoObject*)ex;
1359         g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
1360 }
1361
1362 static MonoExceptionFunc ex_handler = default_ex_handler;
1363
1364 void
1365 mono_install_handler        (MonoExceptionFunc func)
1366 {
1367         ex_handler = func? func: default_ex_handler;
1368 }
1369
1370 /*
1371  * mono_raise_exception:
1372  * @ex: exception object
1373  *
1374  * Signal the runtime that the exception @ex has been raised in unmanaged code.
1375  */
1376 void
1377 mono_raise_exception (MonoException *ex) 
1378 {
1379         ex_handler (ex);
1380 }
1381
1382 MonoWaitHandle *
1383 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
1384 {
1385         MonoWaitHandle *res;
1386
1387         res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
1388
1389         res->handle = handle;
1390
1391         return res;
1392 }
1393
1394 MonoAsyncResult *
1395 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
1396 {
1397         MonoAsyncResult *res;
1398
1399         res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
1400
1401         res->data = data;
1402         res->async_state = state;
1403         res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
1404         res->sync_completed = FALSE;
1405         res->completed = FALSE;
1406
1407         return res;
1408 }
1409
1410 void
1411 mono_message_init (MonoDomain *domain,
1412                    MonoMethodMessage *this, 
1413                    MonoReflectionMethod *method,
1414                    MonoArray *out_args)
1415 {
1416         MonoMethodSignature *sig = method->method->signature;
1417         MonoString *name;
1418         int i, j;
1419         char **names;
1420         guint8 arg_type;
1421
1422         this->method = method;
1423
1424         this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
1425         this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
1426
1427         names = g_new (char *, sig->param_count);
1428         mono_method_get_param_names (method->method, (const char **) names);
1429         this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
1430         
1431         for (i = 0; i < sig->param_count; i++) {
1432                  name = mono_string_new (domain, names [i]);
1433                  mono_array_set (this->names, gpointer, i, name);       
1434         }
1435
1436         g_free (names);
1437         
1438         for (i = 0, j = 0; i < sig->param_count; i++) {
1439
1440                 if (sig->params [i]->byref) {
1441                         if (out_args) {
1442                                 gpointer arg = mono_array_get (out_args, gpointer, j);
1443                                 mono_array_set (this->args, gpointer, i, arg);
1444                                 j++;
1445                         }
1446                         arg_type = 2;
1447                         if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
1448                                 arg_type |= 1;
1449                 } else {
1450                         arg_type = 1;
1451                 }
1452
1453                 mono_array_set (this->arg_types, guint8, i, arg_type);
1454         }
1455 }
1456
1457 /**
1458  * mono_remoting_invoke:
1459  * @real_proxy: pointer to a RealProxy object
1460  * @msg: The MonoMethodMessage to execute
1461  * @exc: used to store exceptions
1462  * @out_args: used to store output arguments
1463  *
1464  * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
1465  * IMessage interface and it is not trivial to extract results from there. So
1466  * we call an helper method PrivateInvoke instead of calling
1467  * RealProxy::Invoke() directly.
1468  *
1469  * Returns: the result object.
1470  */
1471 MonoObject *
1472 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, 
1473                       MonoObject **exc, MonoArray **out_args)
1474 {
1475         static MonoMethod *im = NULL;
1476         gpointer pa [4];
1477
1478         /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
1479
1480         /* FIXME: make this domain dependent */
1481         if (!im) {
1482                 MonoClass *klass;
1483                 int i;
1484
1485                 klass = mono_defaults.real_proxy_class; 
1486                        
1487                 for (i = 0; i < klass->method.count; ++i) {
1488                         if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
1489                             klass->methods [i]->signature->param_count == 4) {
1490                                 im = klass->methods [i];
1491                                 break;
1492                         }
1493                 }
1494         
1495                 g_assert (im);
1496         }
1497
1498         pa [0] = real_proxy;
1499         pa [1] = msg;
1500         pa [2] = exc;
1501         pa [3] = out_args;
1502
1503         return mono_runtime_invoke (im, NULL, pa, exc);
1504 }
1505
1506 MonoObject *
1507 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, 
1508                      MonoObject **exc, MonoArray **out_args) 
1509 {
1510         if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1511
1512                 return mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)target)->rp, 
1513                                              msg, exc, out_args);
1514
1515         } else {
1516                 MonoDomain *domain = mono_domain_get (); 
1517                 MonoMethod *method = msg->method->method;
1518                 MonoMethodSignature *sig = method->signature;
1519                 int i, j, outarg_count = 0;
1520
1521                 for (i = 0; i < sig->param_count; i++) {
1522                         if (sig->params [i]->byref) 
1523                                 outarg_count++;
1524                 }
1525
1526                 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
1527                 *exc = NULL;
1528
1529                 for (i = 0, j = 0; i < sig->param_count; i++) {
1530                         if (sig->params [i]->byref) {
1531                                 gpointer arg;
1532                                 arg = mono_array_get (msg->args, gpointer, i);
1533                                 mono_array_set (*out_args, gpointer, j, arg);
1534                                 j++;
1535                         }
1536                 }
1537
1538                 return mono_runtime_invoke_array (method, target, msg->args, exc);
1539         }
1540 }
1541
1542 void
1543 mono_print_unhandled_exception (MonoObject *exc)
1544 {
1545         char *message = (char *) "";
1546         MonoString *str; 
1547         MonoMethod *method;
1548         MonoClass *klass;
1549         gboolean free_message = FALSE;
1550         gint i;
1551
1552         if (mono_object_isinst (exc, mono_defaults.exception_class)) {
1553                 klass = exc->vtable->klass;
1554                 method = NULL;
1555                 while (klass && method == NULL) {
1556                         for (i = 0; i < klass->method.count; ++i) {
1557                                 method = klass->methods [i];
1558                                 if (!strcmp ("ToString", method->name) &&
1559                                     method->signature->param_count == 0 &&
1560                                     method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
1561                                     method->flags & METHOD_ATTRIBUTE_PUBLIC) {
1562                                         break;
1563                                 }
1564                                 method = NULL;
1565                         }
1566                         
1567                         if (method == NULL)
1568                                 klass = klass->parent;
1569                 }
1570
1571                 g_assert (method);
1572
1573                 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
1574                 if (str) {
1575                         message = mono_string_to_utf8 (str);
1576                         free_message = TRUE;
1577                 }
1578         }                               
1579
1580         /*
1581          * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space, 
1582          *         exc->vtable->klass->name, message);
1583          */
1584         g_printerr ("\nUnhandled Exception: %s\n", message);
1585         
1586         if (free_message)
1587                 g_free (message);
1588 }
1589
1590 /**
1591  * mono_delegate_ctor:
1592  * @this: pointer to an uninitialized delegate object
1593  * @target: target object
1594  * @addr: pointer to native code
1595  *
1596  * This is used to initialize a delegate. We also insert the method_info if
1597  * we find the info with mono_jit_info_table_find().
1598  */
1599 void
1600 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
1601 {
1602         MonoDomain *domain = mono_domain_get ();
1603         MonoDelegate *delegate = (MonoDelegate *)this;
1604         MonoMethod *method = NULL;
1605         MonoClass *class;
1606         MonoJitInfo *ji;
1607
1608         g_assert (this);
1609         g_assert (addr);
1610
1611         class = this->vtable->klass;
1612
1613         if ((ji = mono_jit_info_table_find (domain, addr))) {
1614                 method = ji->method;
1615                 delegate->method_info = mono_method_get_object (domain, method, NULL);
1616         }
1617
1618         if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1619                 g_assert (method);
1620                 method = mono_marshal_get_remoting_invoke (method);
1621                 delegate->method_ptr = mono_compile_method (method);
1622                 delegate->target = target;
1623         } else {
1624                 delegate->method_ptr = addr;
1625                 delegate->target = target;
1626         }
1627 }
1628
1629 /**
1630  * mono_method_call_message_new:
1631  *
1632  * Translates arguments pointers into a Message.
1633  */
1634 MonoMethodMessage *
1635 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke, 
1636                               MonoDelegate **cb, MonoObject **state)
1637 {
1638         MonoDomain *domain = mono_domain_get ();
1639         MonoMethodSignature *sig = method->signature;
1640         MonoMethodMessage *msg;
1641         int i, count, type;
1642
1643         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class); 
1644         
1645         if (invoke) {
1646                 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
1647                 count =  sig->param_count - 2;
1648         } else {
1649                 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
1650                 count =  sig->param_count;
1651         }
1652
1653         for (i = 0; i < count; i++) {
1654                 gpointer vpos;
1655                 MonoClass *class;
1656                 MonoObject *arg;
1657
1658                 if (sig->params [i]->byref)
1659                         vpos = *((gpointer *)params [i]);
1660                 else 
1661                         vpos = params [i];
1662
1663                 type = sig->params [i]->type;
1664                 class = mono_class_from_mono_type (sig->params [i]);
1665
1666                 if (class->valuetype)
1667                         arg = mono_value_box (domain, class, vpos);
1668                 else 
1669                         arg = *((MonoObject **)vpos);
1670                       
1671                 mono_array_set (msg->args, gpointer, i, arg);
1672         }
1673
1674         if (invoke) {
1675                 *cb = *((MonoDelegate **)params [i]);
1676                 i++;
1677                 *state = *((MonoObject **)params [i]);
1678         }
1679
1680         return msg;
1681 }
1682
1683 /**
1684  * mono_method_return_message_restore:
1685  *
1686  * Restore results from message based processing back to arguments pointers
1687  */
1688 void
1689 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
1690 {
1691         MonoMethodSignature *sig = method->signature;
1692         int i, j, type, size;
1693         
1694         for (i = 0, j = 0; i < sig->param_count; i++) {
1695                 MonoType *pt = sig->params [i];
1696
1697                 size = mono_type_stack_size (pt, NULL);
1698
1699                 if (pt->byref) {
1700                         char *arg = mono_array_get (out_args, gpointer, j);
1701                         type = pt->type;
1702                         
1703                         switch (type) {
1704                         case MONO_TYPE_VOID:
1705                                 g_assert_not_reached ();
1706                                 break;
1707                         case MONO_TYPE_U1:
1708                         case MONO_TYPE_I1:
1709                         case MONO_TYPE_BOOLEAN:
1710                         case MONO_TYPE_U2:
1711                         case MONO_TYPE_I2:
1712                         case MONO_TYPE_CHAR:
1713                         case MONO_TYPE_U4:
1714                         case MONO_TYPE_I4:
1715                         case MONO_TYPE_I8:
1716                         case MONO_TYPE_U8:
1717                         case MONO_TYPE_R4:
1718                         case MONO_TYPE_R8:
1719                         case MONO_TYPE_VALUETYPE: {
1720                                 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size); 
1721                                 break;
1722                         }
1723                         case MONO_TYPE_STRING:
1724                         case MONO_TYPE_CLASS: 
1725                         case MONO_TYPE_ARRAY:
1726                         case MONO_TYPE_SZARRAY:
1727                                 *((MonoObject **)params [i]) = (MonoObject *)arg;
1728                                 break;
1729                         default:
1730                                 g_assert_not_reached ();
1731                         }
1732
1733                         j++;
1734                 }
1735         }
1736 }
1737
1738 /**
1739  * mono_load_remote_field:
1740  * @this: pointer to an object
1741  * @klass: klass of the object containing @field
1742  * @field: the field to load
1743  * @res: a storage to store the result
1744  *
1745  * This method is called by the runtime on attempts to load fields of
1746  * transparent proxy objects. @this points to such TP, @klass is the class of
1747  * the object containing @field. @res is a storage location which can be
1748  * used to store the result.
1749  *
1750  * Returns: an address pointing to the value of field.
1751  */
1752 gpointer
1753 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
1754 {
1755         static MonoMethod *getter = NULL;
1756         MonoDomain *domain = mono_domain_get ();
1757         MonoClass *field_class;
1758         MonoMethodMessage *msg;
1759         MonoArray *out_args;
1760         MonoObject *exc;
1761         gpointer tmp;
1762
1763         g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
1764
1765         if (!res)
1766                 res = &tmp;
1767
1768         if (!getter) {
1769                 int i;
1770
1771                 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
1772                         MonoMethod *cm = mono_defaults.object_class->methods [i];
1773                
1774                         if (!strcmp (cm->name, "FieldGetter")) {
1775                                 getter = cm;
1776                                 break;
1777                         }
1778                 }
1779                 g_assert (getter);
1780         }
1781         
1782         field_class = mono_class_from_mono_type (field->type);
1783
1784         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1785         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
1786         mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
1787
1788         mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
1789         mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
1790
1791         mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)this)->rp, msg, &exc, &out_args);
1792
1793         *res = mono_array_get (out_args, MonoObject *, 0);
1794
1795         if (field_class->valuetype) {
1796                 return ((char *)*res) + sizeof (MonoObject);
1797         } else
1798                 return res;
1799 }
1800
1801 /**
1802  * mono_store_remote_field:
1803  * @this: pointer to an object
1804  * @klass: klass of the object containing @field
1805  * @field: the field to load
1806  * @val: the value/object to store
1807  *
1808  * This method is called by the runtime on attempts to store fields of
1809  * transparent proxy objects. @this points to such TP, @klass is the class of
1810  * the object containing @field. @val is the new value to store in @field.
1811  */
1812 void
1813 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
1814 {
1815         static MonoMethod *setter = NULL;
1816         MonoDomain *domain = mono_domain_get ();
1817         MonoClass *field_class;
1818         MonoMethodMessage *msg;
1819         MonoArray *out_args;
1820         MonoObject *exc;
1821         MonoObject *arg;
1822
1823         g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
1824
1825         if (!setter) {
1826                 int i;
1827
1828                 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
1829                         MonoMethod *cm = mono_defaults.object_class->methods [i];
1830                
1831                         if (!strcmp (cm->name, "FieldSetter")) {
1832                                 setter = cm;
1833                                 break;
1834                         }
1835                 }
1836                 g_assert (setter);
1837         }
1838
1839         field_class = mono_class_from_mono_type (field->type);
1840
1841         if (field_class->valuetype)
1842                 arg = mono_value_box (domain, field_class, val);
1843         else 
1844                 arg = *((MonoObject **)val);
1845                 
1846
1847         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1848         mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
1849
1850         mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
1851         mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
1852         mono_array_set (msg->args, gpointer, 2, arg);
1853
1854         mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)this)->rp, msg, &exc, &out_args);
1855 }
1856
1857
1858
1859