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