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