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