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