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