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