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