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