* attribute.cs (GetMarshal): Work even if "DefineCustom" is
[mono.git] / mono / metadata / object.c
1 /*
2  * object.c: Object creation for the Mono runtime
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2001-2004 Ximian, Inc.
9  */
10 #include <config.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <signal.h>
14 #include <string.h>
15 #include <mono/metadata/mono-endian.h>
16 #include <mono/metadata/tabledefs.h>
17 #include <mono/metadata/tokentype.h>
18 #include <mono/metadata/loader.h>
19 #include <mono/metadata/object.h>
20 #include <mono/metadata/gc-internal.h>
21 #include <mono/metadata/exception.h>
22 #include <mono/metadata/domain-internals.h>
23 #include "mono/metadata/metadata-internals.h"
24 #include "mono/metadata/class-internals.h"
25 #include <mono/metadata/assembly.h>
26 #include <mono/metadata/threadpool.h>
27 #include <mono/metadata/marshal.h>
28 #include "mono/metadata/debug-helpers.h"
29 #include "mono/metadata/marshal.h"
30 #include <mono/metadata/threads.h>
31 #include <mono/metadata/threads-types.h>
32 #include <mono/metadata/environment.h>
33 #include "mono/metadata/profiler-private.h"
34 #include "mono/metadata/security-manager.h"
35 #include <mono/os/gc_wrapper.h>
36 #include <mono/utils/strenc.h>
37
38 #ifdef HAVE_BOEHM_GC
39 #define NEED_TO_ZERO_PTRFREE 1
40 #define ALLOC_PTRFREE(obj,vt,size) do { (obj) = GC_MALLOC_ATOMIC ((size)); (obj)->vtable = (vt); (obj)->synchronisation = NULL;} while (0)
41 #define ALLOC_OBJECT(obj,vt,size) do { (obj) = GC_MALLOC ((size)); (obj)->vtable = (vt);} while (0)
42 #ifdef HAVE_GC_GCJ_MALLOC
43 #define CREATION_SPEEDUP 1
44 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
45 #define ALLOC_TYPED(dest,size,type) do { (dest) = GC_GCJ_MALLOC ((size),(type)); } while (0)
46 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) GC_make_descriptor((GC_bitmap)(bitmap),(sz))
47 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) GC_make_descriptor((GC_bitmap)(bitmap),(sz))
48 #else
49 #define GC_NO_DESCRIPTOR (NULL)
50 #define ALLOC_TYPED(dest,size,type) do { (dest) = GC_MALLOC ((size)); *(gpointer*)dest = (type);} while (0)
51 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) NULL
52 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) NULL
53 #endif
54 #else
55 #ifdef HAVE_SGEN_GC
56 #define GC_NO_DESCRIPTOR (NULL)
57 #define ALLOC_PTRFREE(obj,vt,size) do { (obj) = mono_gc_alloc_obj (vt, size);} while (0)
58 #define ALLOC_OBJECT(obj,vt,size) do { (obj) = mono_gc_alloc_obj (vt, size);} while (0)
59 #define ALLOC_TYPED(dest,size,type) do { (dest) = mono_gc_alloc_obj (type, size);} while (0)
60 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) mono_gc_make_descr_for_string ()
61 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) mono_gc_make_descr_for_object ((bitmap), (sz), (objsize))
62 #else
63 #define NEED_TO_ZERO_PTRFREE 1
64 #define GC_NO_DESCRIPTOR (NULL)
65 #define ALLOC_PTRFREE(obj,vt,size) do { (obj) = malloc ((size)); (obj)->vtable = (vt); (obj)->synchronisation = NULL;} while (0)
66 #define ALLOC_OBJECT(obj,vt,size) do { (obj) = calloc (1, (size)); (obj)->vtable = (vt);} while (0)
67 #define ALLOC_TYPED(dest,size,type) do { (dest) = calloc (1, (size)); *(gpointer*)dest = (type);} while (0)
68 #define MAKE_STRING_DESCRIPTOR(bitmap,sz) NULL
69 #define MAKE_DESCRIPTOR(bitmap,sz,objsize) NULL
70 #endif
71 #endif
72
73 static MonoObject* mono_object_new_ptrfree (MonoVTable *vtable);
74 static MonoObject* mono_object_new_ptrfree_box (MonoVTable *vtable);
75
76 static void
77 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value);
78
79 static MonoString*
80 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig);
81
82 void
83 mono_runtime_object_init (MonoObject *this)
84 {
85         MonoMethod *method = NULL;
86         MonoClass *klass = this->vtable->klass;
87
88         method = mono_class_get_method_from_name (klass, ".ctor", 0);
89         g_assert (method);
90
91         if (method->klass->valuetype)
92                 this = mono_object_unbox (this);
93         mono_runtime_invoke (method, this, NULL, NULL);
94 }
95
96 /* The pseudo algorithm for type initialization from the spec
97 Note it doesn't say anything about domains - only threads.
98
99 2. If the type is initialized you are done.
100 2.1. If the type is not yet initialized, try to take an 
101      initialization lock.  
102 2.2. If successful, record this thread as responsible for 
103      initializing the type and proceed to step 2.3.
104 2.2.1. If not, see whether this thread or any thread 
105      waiting for this thread to complete already holds the lock.
106 2.2.2. If so, return since blocking would create a deadlock.  This thread 
107      will now see an incompletely initialized state for the type, 
108      but no deadlock will arise.
109 2.2.3  If not, block until the type is initialized then return.
110 2.3 Initialize the parent type and then all interfaces implemented 
111     by this type.
112 2.4 Execute the type initialization code for this type.
113 2.5 Mark the type as initialized, release the initialization lock, 
114     awaken any threads waiting for this type to be initialized, 
115     and return.
116
117 */
118
119 typedef struct
120 {
121         guint32 initializing_tid;
122         guint32 waiting_count;
123         gboolean done;
124         CRITICAL_SECTION initialization_section;
125 } TypeInitializationLock;
126
127 /* for locking access to type_initialization_hash and blocked_thread_hash */
128 static CRITICAL_SECTION type_initialization_section;
129
130 /* from vtable to lock */
131 static GHashTable *type_initialization_hash;
132
133 /* from thread id to thread id being waited on */
134 static GHashTable *blocked_thread_hash;
135
136 /* Main thread */
137 static MonoThread *main_thread;
138
139 /**
140  * mono_thread_set_main:
141  * @thread: thread to set as the main thread
142  *
143  * This function can be used to instruct the runtime to treat @thread
144  * as the main thread, ie, the thread that would normally execute the Main()
145  * method. This basically means that at the end of @thread, the runtime will
146  * wait for the existing foreground threads to quit and other such details.
147  */
148 void
149 mono_thread_set_main (MonoThread *thread)
150 {
151         main_thread = thread;
152 }
153
154 MonoThread*
155 mono_thread_get_main (void)
156 {
157         return main_thread;
158 }
159
160 void
161 mono_type_initialization_init (void)
162 {
163         InitializeCriticalSection (&type_initialization_section);
164         type_initialization_hash = g_hash_table_new (NULL, NULL);
165         blocked_thread_hash = g_hash_table_new (NULL, NULL);
166 }
167
168 /*
169  * mono_runtime_class_init:
170  * @vtable: vtable that needs to be initialized
171  *
172  * This routine calls the class constructor for @vtable.
173  */
174 void
175 mono_runtime_class_init (MonoVTable *vtable)
176 {
177         MonoException *exc;
178         MonoException *exc_to_throw;
179         MonoMethod *method = NULL;
180         MonoClass *klass;
181         gchar *full_name;
182
183         MONO_ARCH_SAVE_REGS;
184
185         if (vtable->initialized)
186                 return;
187
188         exc = NULL;
189         klass = vtable->klass;
190
191         method = mono_class_get_cctor (klass);
192
193         if (method) {
194                 MonoDomain *domain = vtable->domain;
195                 TypeInitializationLock *lock;
196                 guint32 tid = GetCurrentThreadId();
197                 int do_initialization = 0;
198                 MonoDomain *last_domain = NULL;
199
200                 EnterCriticalSection (&type_initialization_section);
201                 /* double check... */
202                 if (vtable->initialized) {
203                         LeaveCriticalSection (&type_initialization_section);
204                         return;
205                 }
206                 lock = g_hash_table_lookup (type_initialization_hash, vtable);
207                 if (lock == NULL) {
208                         /* This thread will get to do the initialization */
209                         if (mono_domain_get () != domain) {
210                                 /* Transfer into the target domain */
211                                 last_domain = mono_domain_get ();
212                                 if (!mono_domain_set (domain, FALSE)) {
213                                         vtable->initialized = 1;
214                                         LeaveCriticalSection (&type_initialization_section);
215                                         mono_raise_exception (mono_get_exception_appdomain_unloaded ());
216                                 }
217                         }
218                         lock = g_malloc (sizeof(TypeInitializationLock));
219                         InitializeCriticalSection (&lock->initialization_section);
220                         lock->initializing_tid = tid;
221                         lock->waiting_count = 1;
222                         lock->done = FALSE;
223                         /* grab the vtable lock while this thread still owns type_initialization_section */
224                         EnterCriticalSection (&lock->initialization_section);
225                         g_hash_table_insert (type_initialization_hash, vtable, lock);
226                         do_initialization = 1;
227                 } else {
228                         gpointer blocked;
229                         TypeInitializationLock *pending_lock;
230
231                         if (lock->initializing_tid == tid || lock->done) {
232                                 LeaveCriticalSection (&type_initialization_section);
233                                 return;
234                         }
235                         /* see if the thread doing the initialization is already blocked on this thread */
236                         blocked = GUINT_TO_POINTER (lock->initializing_tid);
237                         while ((pending_lock = (TypeInitializationLock*) g_hash_table_lookup (blocked_thread_hash, blocked))) {
238                                 if (pending_lock->initializing_tid == tid) {
239                                         if (!pending_lock->done) {
240                                                 LeaveCriticalSection (&type_initialization_section);
241                                                 return;
242                                         } else {
243                                                 /* the thread doing the initialization is blocked on this thread,
244                                                    but on a lock that has already been freed. It just hasn't got
245                                                    time to awake */
246                                                 break;
247                                         }
248                                 }
249                                 blocked = GUINT_TO_POINTER (pending_lock->initializing_tid);
250                         }
251                         ++lock->waiting_count;
252                         /* record the fact that we are waiting on the initializing thread */
253                         g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock);
254                 }
255                 LeaveCriticalSection (&type_initialization_section);
256
257                 if (do_initialization) {
258                         mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
259                         if (last_domain)
260                                 mono_domain_set (last_domain, TRUE);
261                         lock->done = TRUE;
262                         LeaveCriticalSection (&lock->initialization_section);
263                 } else {
264                         /* this just blocks until the initializing thread is done */
265                         EnterCriticalSection (&lock->initialization_section);
266                         LeaveCriticalSection (&lock->initialization_section);
267                 }
268
269                 EnterCriticalSection (&type_initialization_section);
270                 if (lock->initializing_tid != tid)
271                         g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
272                 --lock->waiting_count;
273                 if (lock->waiting_count == 0) {
274                         DeleteCriticalSection (&lock->initialization_section);
275                         g_hash_table_remove (type_initialization_hash, vtable);
276                         g_free (lock);
277                 }
278                 vtable->initialized = 1;
279                 /* FIXME: if the cctor fails, the type must be marked as unusable */
280                 LeaveCriticalSection (&type_initialization_section);
281         } else {
282                 vtable->initialized = 1;
283                 return;
284         }
285
286         if (exc == NULL ||
287             (klass->image == mono_defaults.corlib &&            
288              !strcmp (klass->name_space, "System") &&
289              !strcmp (klass->name, "TypeInitializationException")))
290                 return; /* No static constructor found or avoid infinite loop */
291
292         if (klass->name_space && *klass->name_space)
293                 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
294         else
295                 full_name = g_strdup (klass->name);
296
297         exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
298         g_free (full_name);
299
300         mono_raise_exception (exc_to_throw);
301 }
302
303 static
304 gboolean release_type_locks (gpointer key, gpointer value, gpointer user)
305 {
306         TypeInitializationLock *lock = (TypeInitializationLock*) value;
307         if (lock->initializing_tid == GPOINTER_TO_UINT (user) && !lock->done) {
308                 lock->done = TRUE;
309                 LeaveCriticalSection (&lock->initialization_section);
310                 --lock->waiting_count;
311                 if (lock->waiting_count == 0) {
312                         DeleteCriticalSection (&lock->initialization_section);
313                         g_free (lock);
314                         return TRUE;
315                 }
316         }
317         return FALSE;
318 }
319
320 void
321 mono_release_type_locks (MonoThread *thread)
322 {
323         EnterCriticalSection (&type_initialization_section);
324         g_hash_table_foreach_remove (type_initialization_hash, release_type_locks, (gpointer)(gsize)(thread->tid));
325         LeaveCriticalSection (&type_initialization_section);
326 }
327
328 static gpointer
329 default_trampoline (MonoMethod *method)
330 {
331         return method;
332 }
333
334 static gpointer
335 default_remoting_trampoline (MonoMethod *method, MonoRemotingTarget target)
336 {
337         g_error ("remoting not installed");
338         return NULL;
339 }
340
341 static gpointer
342 default_delegate_trampoline (MonoMethod *method, gpointer addr)
343 {
344         g_assert_not_reached ();
345         return NULL;
346 }
347
348 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
349 static MonoRemotingTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
350 static MonoDelegateTrampoline arch_create_delegate_trampoline = default_delegate_trampoline;
351
352 void
353 mono_install_trampoline (MonoTrampoline func) 
354 {
355         arch_create_jit_trampoline = func? func: default_trampoline;
356 }
357
358 void
359 mono_install_remoting_trampoline (MonoRemotingTrampoline func) 
360 {
361         arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
362 }
363
364 void
365 mono_install_delegate_trampoline (MonoDelegateTrampoline func) 
366 {
367         arch_create_delegate_trampoline = func? func: default_delegate_trampoline;
368 }
369
370 static MonoCompileFunc default_mono_compile_method = NULL;
371
372 /**
373  * mono_install_compile_method:
374  * @func: function to install
375  *
376  * This is a VM internal routine
377  */
378 void        
379 mono_install_compile_method (MonoCompileFunc func)
380 {
381         default_mono_compile_method = func;
382 }
383
384 /**
385  * mono_compile_method:
386  * @method: The method to compile.
387  *
388  * This JIT-compiles the method, and returns the pointer to the native code
389  * produced.
390  */
391 gpointer 
392 mono_compile_method (MonoMethod *method)
393 {
394         if (!default_mono_compile_method) {
395                 g_error ("compile method called on uninitialized runtime");
396                 return NULL;
397         }
398         return default_mono_compile_method (method);
399 }
400
401 static MonoFreeMethodFunc default_mono_free_method = NULL;
402
403 /**
404  * mono_install_free_method:
405  * @func: pointer to the MonoFreeMethodFunc used to release a method
406  *
407  * This is an internal VM routine, it is used for the engines to
408  * register a handler to release the resources associated with a method.
409  *
410  * Methods are freed when no more references to the delegate that holds
411  * them are left.
412  */
413 void
414 mono_install_free_method (MonoFreeMethodFunc func)
415 {
416         default_mono_free_method = func;
417 }
418
419 /**
420  * mono_runtime_free_method:
421  * @domain; domain where the method is hosted
422  * @method: method to release
423  *
424  * This routine is invoked to free the resources associated with
425  * a method that has been JIT compiled.  This is used to discard
426  * methods that were used only temporarily (for example, used in marshalling)
427  *
428  */
429 void
430 mono_runtime_free_method (MonoDomain *domain, MonoMethod *method)
431 {
432         if (default_mono_free_method != NULL)
433                 default_mono_free_method (domain, method);
434
435         mono_free_method (method);
436 }
437
438 static MonoInitVTableFunc init_vtable_func = NULL;
439
440 /**
441  * mono_install_init_vtable:
442  * @func: pointer to the function to be installed
443  *
444  *   Register a function which will be called by the runtime to initialize the
445  * method pointers inside a vtable. The JIT can use this function to load the
446  * vtable from the AOT file for example.
447  */
448 void
449 mono_install_init_vtable (MonoInitVTableFunc func)
450 {
451         init_vtable_func = func;
452 }
453
454 /*
455  * The vtables in the root appdomain are assumed to be reachable by other 
456  * roots, and we don't use typed allocation in the other domains.
457  */
458
459 /* The sync block is no longer a GC pointer */
460 #define GC_HEADER_BITMAP (0)
461
462 #define BITMAP_EL_SIZE (sizeof (gsize) * 8)
463
464 static gsize*
465 compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int *max_set)
466 {
467         MonoClassField *field;
468         MonoClass *p;
469         guint32 pos;
470         int max_size = class->instance_size / sizeof (gpointer);
471         if (max_size > size) {
472                 bitmap = g_malloc0 (sizeof (gsize) * ((max_size) + 1));
473         }
474
475         for (p = class; p != NULL; p = p->parent) {
476                 gpointer iter = NULL;
477                 while ((field = mono_class_get_fields (p, &iter))) {
478                         MonoType *type;
479
480                         if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA))
481                                 continue;
482                         /* FIXME: should not happen, flag as type load error */
483                         if (field->type->byref)
484                                 break;
485
486                         pos = field->offset / sizeof (gpointer);
487                         pos += offset;
488
489                         type = mono_type_get_underlying_type (field->type);
490                         switch (type->type) {
491                         /* FIXME: _I and _U and _PTR should be removed eventually */
492                         case MONO_TYPE_I:
493                         case MONO_TYPE_U:
494                         case MONO_TYPE_PTR:
495                         case MONO_TYPE_FNPTR:
496                         case MONO_TYPE_STRING:
497                         case MONO_TYPE_SZARRAY:
498                         case MONO_TYPE_CLASS:
499                         case MONO_TYPE_OBJECT:
500                         case MONO_TYPE_ARRAY:
501                                 g_assert ((field->offset % sizeof(gpointer)) == 0);
502
503                                 bitmap [pos / BITMAP_EL_SIZE] |= ((gsize)1) << (pos % BITMAP_EL_SIZE);
504                                 *max_set = MAX (*max_set, pos);
505                                 break;
506                         case MONO_TYPE_VALUETYPE: {
507                                 MonoClass *fclass = field->type->data.klass;
508                                 if (fclass->has_references) {
509                                         /* remove the object header */
510                                         compute_class_bitmap (fclass, bitmap, size, pos - (sizeof (MonoObject) / sizeof (gpointer)), max_set);
511                                 }
512                                 break;
513                         }
514                         case MONO_TYPE_I1:
515                         case MONO_TYPE_U1:
516                         case MONO_TYPE_I2:
517                         case MONO_TYPE_U2:
518                         case MONO_TYPE_I4:
519                         case MONO_TYPE_U4:
520                         case MONO_TYPE_I8:
521                         case MONO_TYPE_U8:
522                         case MONO_TYPE_R4:
523                         case MONO_TYPE_R8:
524                         case MONO_TYPE_BOOLEAN:
525                         case MONO_TYPE_CHAR:
526                                 break;
527                         default:
528                                 g_assert_not_reached ();
529                                 break;
530                         }
531                 }
532         }
533         return bitmap;
534 }
535
536 static void
537 mono_class_compute_gc_descriptor (MonoClass *class)
538 {
539         int max_set = 0;
540         gsize *bitmap;
541         gsize default_bitmap [4] = {0};
542         static gboolean gcj_inited = FALSE;
543
544         if (!gcj_inited) {
545                 mono_loader_lock ();
546
547                 mono_register_jit_icall (mono_object_new_ptrfree, "mono_object_new_ptrfree", mono_create_icall_signature ("object ptr"), FALSE);
548                 mono_register_jit_icall (mono_object_new_ptrfree_box, "mono_object_new_ptrfree_box", mono_create_icall_signature ("object ptr"), FALSE);
549                 mono_register_jit_icall (mono_object_new_fast, "mono_object_new_fast", mono_create_icall_signature ("object ptr"), FALSE);
550
551 #ifdef HAVE_GC_GCJ_MALLOC
552
553                 GC_init_gcj_malloc (5, NULL);
554
555 #ifdef GC_REDIRECT_TO_LOCAL
556                 mono_register_jit_icall (GC_local_gcj_malloc, "GC_local_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
557                 mono_register_jit_icall (GC_local_gcj_fast_malloc, "GC_local_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
558 #endif
559                 mono_register_jit_icall (GC_gcj_malloc, "GC_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
560                 mono_register_jit_icall (GC_gcj_fast_malloc, "GC_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
561 #endif
562                 gcj_inited = TRUE;
563                 mono_loader_unlock ();
564         }
565
566         if (!class->inited)
567                 mono_class_init (class);
568
569         if (class->gc_descr_inited)
570                 return;
571
572         class->gc_descr_inited = TRUE;
573         class->gc_descr = GC_NO_DESCRIPTOR;
574
575         if (class->generic_class || class->generic_container)
576                 /* bug #75479 */
577                 return;
578
579         bitmap = default_bitmap;
580         if (class == mono_defaults.string_class) {
581                 class->gc_descr = (gpointer)MAKE_STRING_DESCRIPTOR (bitmap, 2);
582         } else if (class->rank) {
583                 mono_class_compute_gc_descriptor (class->element_class);
584 #ifdef HAVE_SGEN_GC
585                 /* libgc has no usable support for arrays... */
586                 if (!class->element_class->valuetype) {
587                         gsize abm = 1;
588                         class->gc_descr = mono_gc_make_descr_for_array (TRUE, &abm, 1, sizeof (gpointer));
589                         /*printf ("new array descriptor: 0x%x for %s.%s\n", class->gc_descr,
590                                 class->name_space, class->name);*/
591                 } else {
592                         /* remove the object header */
593                         bitmap = compute_class_bitmap (class->element_class, default_bitmap, sizeof (default_bitmap) * 8, - (sizeof (MonoObject) / sizeof (gpointer)), &max_set);
594                         class->gc_descr = mono_gc_make_descr_for_array (TRUE, bitmap, mono_array_element_size (class) / sizeof (gpointer), mono_array_element_size (class));
595                         /*printf ("new vt array descriptor: 0x%x for %s.%s\n", class->gc_descr,
596                                 class->name_space, class->name);*/
597                         if (bitmap != default_bitmap)
598                                 g_free (bitmap);
599                 }
600 #endif
601         } else {
602                 /*static int count = 0;
603                 if (count++ > 58)
604                         return;*/
605                 bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set);
606 #ifdef HAVE_BOEHM_GC
607                 /* It seems there are issues when the bitmap doesn't fit: play it safe */
608                 if (max_set >= 30) {
609                         /*g_print ("disabling typed alloc (%d) for %s.%s\n", max_set, class->name_space, class->name);*/
610                         if (bitmap != default_bitmap)
611                                 g_free (bitmap);
612                         return;
613                 }
614 #endif
615                 class->gc_descr = (gpointer)MAKE_DESCRIPTOR (bitmap, max_set + 1, class->instance_size);
616                 /*printf ("new descriptor: %p 0x%x for %s.%s\n", class->gc_descr, bitmap [0], class->name_space, class->name);*/
617                 if (bitmap != default_bitmap)
618                         g_free (bitmap);
619         }
620 }
621
622 /**
623  * field_is_special_static:
624  * @fklass: The MonoClass to look up.
625  * @field: The MonoClassField describing the field.
626  *
627  * Returns: SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
628  * SPECIAL_STATIC_NONE otherwise.
629  */
630 static gint32
631 field_is_special_static (MonoClass *fklass, MonoClassField *field)
632 {
633         MonoCustomAttrInfo *ainfo;
634         int i;
635         ainfo = mono_custom_attrs_from_field (fklass, field);
636         if (!ainfo)
637                 return FALSE;
638         for (i = 0; i < ainfo->num_attrs; ++i) {
639                 MonoClass *klass = ainfo->attrs [i].ctor->klass;
640                 if (klass->image == mono_defaults.corlib) {
641                         if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
642                                 mono_custom_attrs_free (ainfo);
643                                 return SPECIAL_STATIC_THREAD;
644                         }
645                         else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
646                                 mono_custom_attrs_free (ainfo);
647                                 return SPECIAL_STATIC_CONTEXT;
648                         }
649                 }
650         }
651         mono_custom_attrs_free (ainfo);
652         return SPECIAL_STATIC_NONE;
653 }
654
655 static MonoVTable *mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class);
656
657 /**
658  * mono_class_vtable:
659  * @domain: the application domain
660  * @class: the class to initialize
661  *
662  * VTables are domain specific because we create domain specific code, and 
663  * they contain the domain specific static class data.
664  */
665 MonoVTable *
666 mono_class_vtable (MonoDomain *domain, MonoClass *class)
667 {
668         MonoClassRuntimeInfo *runtime_info;
669
670         g_assert (class);
671
672         /* this check can be inlined in jitted code, too */
673         runtime_info = class->runtime_info;
674         if (runtime_info && runtime_info->max_domain >= domain->domain_id && runtime_info->domain_vtables [domain->domain_id])
675                 return runtime_info->domain_vtables [domain->domain_id];
676         return mono_class_create_runtime_vtable (domain, class);
677 }
678
679 static MonoVTable *
680 mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
681 {
682         MonoVTable *vt;
683         MonoClassRuntimeInfo *runtime_info, *old_info;
684         MonoClassField *field;
685         char *t;
686         int i;
687         gboolean inited = FALSE;
688         guint32 vtable_size;
689         guint32 cindex;
690         guint32 constant_cols [MONO_CONSTANT_SIZE];
691         gpointer iter;
692
693         mono_domain_lock (domain);
694         runtime_info = class->runtime_info;
695         if (runtime_info && runtime_info->max_domain >= domain->domain_id && runtime_info->domain_vtables [domain->domain_id]) {
696                 mono_domain_unlock (domain);
697                 return runtime_info->domain_vtables [domain->domain_id];
698         }
699         if (!class->inited)
700                 mono_class_init (class);
701
702         mono_stats.used_class_count++;
703         mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
704
705         vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
706
707         vt = mono_mempool_alloc0 (domain->mp,  vtable_size);
708
709         vt->klass = class;
710         vt->rank = class->rank;
711         vt->domain = domain;
712
713         mono_class_compute_gc_descriptor (class);
714                 /*
715                  * We can't use typed allocation in the non-root domains, since the
716                  * collector needs the GC descriptor stored in the vtable even after
717                  * the mempool containing the vtable is destroyed when the domain is
718                  * unloaded. An alternative might be to allocate vtables in the GC
719                  * heap, but this does not seem to work (it leads to crashes inside
720                  * libgc). If that approach is tried, two gc descriptors need to be
721                  * allocated for each class: one for the root domain, and one for all
722                  * other domains. The second descriptor should contain a bit for the
723                  * vtable field in MonoObject, since we can no longer assume the 
724                  * vtable is reachable by other roots after the appdomain is unloaded.
725                  */
726 #ifdef HAVE_BOEHM_GC
727         if (domain != mono_get_root_domain ())
728                 vt->gc_descr = GC_NO_DESCRIPTOR;
729         else
730 #endif
731                 vt->gc_descr = class->gc_descr;
732
733         if (class->class_size) {
734                 if (class->has_static_refs)
735                         vt->data = mono_gc_alloc_fixed (class->class_size, NULL);
736                 else
737                         vt->data = mono_mempool_alloc0 (domain->mp, class->class_size);
738                 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
739                 mono_stats.class_static_data_size += class->class_size;
740         }
741
742         cindex = -1;
743         iter = NULL;
744         while ((field = mono_class_get_fields (class, &iter))) {
745                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
746                         continue;
747                 if (mono_field_is_deleted (field))
748                         continue;
749                 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
750                         gint32 special_static = field_is_special_static (class, field);
751                         if (special_static != SPECIAL_STATIC_NONE) {
752                                 guint32 size, offset;
753                                 int align;
754                                 size = mono_type_size (field->type, &align);
755                                 offset = mono_alloc_special_static_data (special_static, size, align);
756                                 if (!domain->special_static_fields)
757                                         domain->special_static_fields = g_hash_table_new (NULL, NULL);
758                                 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
759                                 continue;
760                         }
761                 }
762                 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
763                         MonoClass *fklass = mono_class_from_mono_type (field->type);
764                         g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT));
765                         t = (char*)vt->data + field->offset;
766                         if (fklass->valuetype) {
767                                 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
768                         } else {
769                                 /* it's a pointer type: add check */
770                                 g_assert ((fklass->byval_arg.type == MONO_TYPE_PTR) || (fklass->byval_arg.type == MONO_TYPE_FNPTR));
771                                 *t = *(char *)field->data;
772                         }
773                         continue;
774                 }
775                 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
776                         continue;
777
778                 /* later do this only on demand if needed */
779                 if (!field->data) {
780                         cindex = mono_metadata_get_constant_index (class->image, mono_class_get_field_token (field), cindex + 1);
781                         g_assert (cindex);
782                         g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
783
784                         mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
785                         field->def_type = constant_cols [MONO_CONSTANT_TYPE];
786                         field->data = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
787                 }
788                 
789         }
790
791         vt->max_interface_id = class->max_interface_id;
792         
793         vt->interface_offsets = mono_mempool_alloc0 (domain->mp, 
794                 sizeof (gpointer) * (class->max_interface_id + 1));
795
796         /* initialize interface offsets */
797         for (i = 0; i <= class->max_interface_id; ++i) {
798                 int slot = class->interface_offsets [i];
799                 if (slot >= 0)
800                         vt->interface_offsets [i] = &(vt->vtable [slot]);
801         }
802
803         /* 
804          * arch_create_jit_trampoline () can recursively call this function again
805          * because it compiles icall methods right away.
806          */
807         /* FIXME: class_vtable_hash is basically obsolete now: remove as soon
808          * as we change the code in appdomain.c to invalidate vtables by
809          * looking at the possible MonoClasses created for the domain.
810          * Or we can reuse static_data_hash, by using vtable as a key
811          * and always inserting into that hash.
812          */
813         g_hash_table_insert (domain->class_vtable_hash, class, vt);
814         /* class->runtime_info is protected by the loader lock, both when
815          * it it enlarged and when it is stored info.
816          */
817         mono_loader_lock ();
818         old_info = class->runtime_info;
819         if (old_info && old_info->max_domain >= domain->domain_id) {
820                 /* someone already created a large enough runtime info */
821                 old_info->domain_vtables [domain->domain_id] = vt;
822         } else {
823                 int new_size = domain->domain_id;
824                 if (old_info)
825                         new_size = MAX (new_size, old_info->max_domain);
826                 new_size++;
827                 /* make the new size a power of two */
828                 i = 2;
829                 while (new_size > i)
830                         i <<= 1;
831                 new_size = i;
832                 /* this is a bounded memory retention issue: may want to 
833                  * handle it differently when we'll have a rcu-like system.
834                  */
835                 runtime_info = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClassRuntimeInfo) + new_size * sizeof (gpointer));
836                 runtime_info->max_domain = new_size - 1;
837                 /* copy the stuff from the older info */
838                 if (old_info) {
839                         memcpy (runtime_info->domain_vtables, old_info->domain_vtables, (old_info->max_domain + 1) * sizeof (gpointer));
840                 }
841                 runtime_info->domain_vtables [domain->domain_id] = vt;
842                 /* keep this last (add membarrier) */
843                 class->runtime_info = runtime_info;
844         }
845         mono_loader_unlock ();
846
847         /* initialize vtable */
848         if (init_vtable_func)
849                 inited = init_vtable_func (vt);
850
851         if (!inited) {
852                 mono_class_setup_vtable (class);
853
854                 for (i = 0; i < class->vtable_size; ++i) {
855                         MonoMethod *cm;
856
857                         if ((cm = class->vtable [i])) {
858                                 if (mono_method_signature (cm)->generic_param_count)
859                                         vt->vtable [i] = cm;
860                                 else
861                                         vt->vtable [i] = arch_create_jit_trampoline (cm);
862                         }
863                 }
864         }
865
866         mono_domain_unlock (domain);
867
868         /* Initialization is now complete, we can throw if the InheritanceDemand aren't satisfied */
869         if (mono_is_security_manager_active () && (class->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND)) {
870                 MonoException *exc = mono_class_get_exception_for_failure (class);
871                 g_assert (exc);
872                 mono_raise_exception (exc);
873         }
874
875         /* make sure the the parent is initialized */
876         if (class->parent)
877                 mono_class_vtable (domain, class->parent);
878
879         vt->type = mono_type_get_object (domain, &class->byval_arg);
880         if (class->contextbound)
881                 vt->remote = 1;
882         else
883                 vt->remote = 0;
884
885         return vt;
886 }
887
888 /**
889  * mono_class_proxy_vtable:
890  * @domain: the application domain
891  * @remove_class: the remote class
892  *
893  * Creates a vtable for transparent proxies. It is basically
894  * a copy of the real vtable of the class wrapped in @remote_class,
895  * but all function pointers invoke the remoting functions, and
896  * vtable->klass points to the transparent proxy class, and not to @class.
897  */
898 static MonoVTable *
899 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRemotingTarget target_type)
900 {
901         MonoVTable *vt, *pvt;
902         int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
903         MonoClass *k;
904         GSList *extra_interfaces = NULL;
905         MonoClass *class = remote_class->proxy_class;
906
907         vt = mono_class_vtable (domain, class);
908         max_interface_id = vt->max_interface_id;
909         
910         /* Calculate vtable space for extra interfaces */
911         for (j = 0; j < remote_class->interface_count; j++) {
912                 MonoClass* iclass = remote_class->interfaces[j];
913                 GPtrArray *ifaces;
914                 int method_count;
915
916                 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != -1) 
917                         continue;       /* interface implemented by the class */
918                 if (g_slist_find (extra_interfaces, iclass))
919                         continue;
920                         
921                 extra_interfaces = g_slist_prepend (extra_interfaces, iclass);
922                 
923                 method_count = mono_class_num_methods (iclass);
924         
925                 ifaces = mono_class_get_implemented_interfaces (iclass);
926                 if (ifaces) {
927                         for (i = 0; i < ifaces->len; ++i) {
928                                 MonoClass *ic = g_ptr_array_index (ifaces, i);
929                                 if (ic->interface_id <= class->max_interface_id && class->interface_offsets[ic->interface_id] != -1) 
930                                         continue;       /* interface implemented by the class */
931                                 if (g_slist_find (extra_interfaces, ic))
932                                         continue;
933                                 extra_interfaces = g_slist_prepend (extra_interfaces, ic);
934                                 method_count += mono_class_num_methods (ic);
935                         }
936                         g_ptr_array_free (ifaces, TRUE);
937                 }
938
939                 extra_interface_vtsize += method_count * sizeof (gpointer);
940                 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
941         }
942
943         vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
944
945         mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
946
947         pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
948         memcpy (pvt, vt, vtsize);
949
950         pvt->klass = mono_defaults.transparent_proxy_class;
951         /* we need to keep the GC descriptor for a transparent proxy or we confuse the precise GC */
952         pvt->gc_descr = mono_defaults.transparent_proxy_class->gc_descr;
953
954         /* initialize vtable */
955         mono_class_setup_vtable (class);
956         for (i = 0; i < class->vtable_size; ++i) {
957                 MonoMethod *cm;
958                     
959                 if ((cm = class->vtable [i]))
960                         pvt->vtable [i] = arch_create_remoting_trampoline (cm, target_type);
961         }
962
963         if (class->flags & TYPE_ATTRIBUTE_ABSTRACT) {
964                 /* create trampolines for abstract methods */
965                 for (k = class; k; k = k->parent) {
966                         MonoMethod* m;
967                         gpointer iter = NULL;
968                         while ((m = mono_class_get_methods (k, &iter)))
969                                 if (!pvt->vtable [m->slot])
970                                         pvt->vtable [m->slot] = arch_create_remoting_trampoline (m, target_type);
971                 }
972         }
973
974         pvt->max_interface_id = max_interface_id;
975         pvt->interface_offsets = mono_mempool_alloc0 (domain->mp, 
976                         sizeof (gpointer) * (max_interface_id + 1));
977
978         /* initialize interface offsets */
979         for (i = 0; i <= class->max_interface_id; ++i) {
980                 int slot = class->interface_offsets [i];
981                 if (slot >= 0)
982                         pvt->interface_offsets [i] = &(pvt->vtable [slot]);
983         }
984
985         if (extra_interfaces) {
986                 int slot = class->vtable_size;
987                 MonoClass* interf;
988                 gpointer iter;
989                 MonoMethod* cm;
990                 GSList *list_item;
991
992                 /* Create trampolines for the methods of the interfaces */
993                 for (list_item = extra_interfaces; list_item != NULL; list_item=list_item->next) {
994                         interf = list_item->data;
995                         pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
996
997                         iter = NULL;
998                         j = 0;
999                         while ((cm = mono_class_get_methods (interf, &iter)))
1000                                 pvt->vtable [slot + j++] = arch_create_remoting_trampoline (cm, target_type);
1001                         
1002                         slot += mono_class_num_methods (interf);
1003                 }
1004                 g_slist_free (extra_interfaces);
1005         }
1006
1007         return pvt;
1008 }
1009
1010 /**
1011  * create_remote_class_key:
1012  * Creates an array of pointers that can be used as a hash key for a remote class.
1013  * The first element of the array is the number of pointers.
1014  */
1015 static gpointer*
1016 create_remote_class_key (MonoRemoteClass *remote_class, MonoClass *extra_class)
1017 {
1018         gpointer *key;
1019         int i, j;
1020         
1021         if (remote_class == NULL) {
1022                 if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1023                         key = g_malloc (sizeof(gpointer) * 3);
1024                         key [0] = GINT_TO_POINTER (2);
1025                         key [1] = mono_defaults.marshalbyrefobject_class;
1026                         key [2] = extra_class;
1027                 } else {
1028                         key = g_malloc (sizeof(gpointer) * 2);
1029                         key [0] = GINT_TO_POINTER (1);
1030                         key [1] = extra_class;
1031                 }
1032         } else {
1033                 if (extra_class != NULL && (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
1034                         key = g_malloc (sizeof(gpointer) * (remote_class->interface_count + 3));
1035                         key [0] = GINT_TO_POINTER (remote_class->interface_count + 2);
1036                         key [1] = remote_class->proxy_class;
1037
1038                         // Keep the list of interfaces sorted
1039                         for (i = 0, j = 2; i < remote_class->interface_count; i++, j++) {
1040                                 if (extra_class && remote_class->interfaces [i] > extra_class) {
1041                                         key [j++] = extra_class;
1042                                         extra_class = NULL;
1043                                 }
1044                                 key [j] = remote_class->interfaces [i];
1045                         }
1046                         if (extra_class)
1047                                 key [j] = extra_class;
1048                 } else {
1049                         // Replace the old class. The interface list is the same
1050                         key = g_malloc (sizeof(gpointer) * (remote_class->interface_count + 2));
1051                         key [0] = GINT_TO_POINTER (remote_class->interface_count + 1);
1052                         key [1] = extra_class != NULL ? extra_class : remote_class->proxy_class;
1053                         for (i = 0; i < remote_class->interface_count; i++)
1054                                 key [2 + i] = remote_class->interfaces [i];
1055                 }
1056         }
1057         
1058         return key;
1059 }
1060
1061 /**
1062  * mono_remote_class:
1063  * @domain: the application domain
1064  * @class_name: name of the remote class
1065  *
1066  * Creates and initializes a MonoRemoteClass object for a remote type. 
1067  * 
1068  */
1069 MonoRemoteClass*
1070 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
1071 {
1072         MonoRemoteClass *rc;
1073         gpointer* key;
1074         
1075         key = create_remote_class_key (NULL, proxy_class);
1076         
1077         mono_domain_lock (domain);
1078         rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, key);
1079
1080         if (rc) {
1081                 g_free (key);
1082                 mono_domain_unlock (domain);
1083                 return rc;
1084         }
1085
1086         if (proxy_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1087                 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*));
1088                 rc->interface_count = 1;
1089                 rc->interfaces [0] = proxy_class;
1090                 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
1091         } else {
1092                 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
1093                 rc->interface_count = 0;
1094                 rc->proxy_class = proxy_class;
1095         }
1096         
1097         rc->default_vtable = NULL;
1098         rc->xdomain_vtable = NULL;
1099         rc->proxy_class_name = mono_string_to_utf8 (class_name);
1100
1101         mono_g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
1102
1103         mono_domain_unlock (domain);
1104         return rc;
1105 }
1106
1107 /**
1108  * clone_remote_class:
1109  * Creates a copy of the remote_class, adding the provided class or interface
1110  */
1111 static MonoRemoteClass*
1112 clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass *extra_class)
1113 {
1114         MonoRemoteClass *rc;
1115         gpointer* key;
1116         
1117         key = create_remote_class_key (remote_class, extra_class);
1118         rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, key);
1119         if (rc != NULL) {
1120                 g_free (key);
1121                 return rc;
1122         }
1123
1124         if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1125                 int i,j;
1126                 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*) * (remote_class->interface_count + 1));
1127                 rc->proxy_class = remote_class->proxy_class;
1128                 rc->interface_count = remote_class->interface_count + 1;
1129                 
1130                 // Keep the list of interfaces sorted, since the hash key of
1131                 // the remote class depends on this
1132                 for (i = 0, j = 0; i < remote_class->interface_count; i++, j++) {
1133                         if (remote_class->interfaces [i] > extra_class && i == j)
1134                                 rc->interfaces [j++] = extra_class;
1135                         rc->interfaces [j] = remote_class->interfaces [i];
1136                 }
1137                 if (i == j)
1138                         rc->interfaces [j] = extra_class;
1139         } else {
1140                 // Replace the old class. The interface array is the same
1141                 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*) * remote_class->interface_count);
1142                 rc->proxy_class = extra_class;
1143                 rc->interface_count = remote_class->interface_count;
1144                 if (rc->interface_count > 0)
1145                         memcpy (rc->interfaces, remote_class->interfaces, rc->interface_count * sizeof (MonoClass*));
1146         }
1147         
1148         rc->default_vtable = NULL;
1149         rc->xdomain_vtable = NULL;
1150         rc->proxy_class_name = remote_class->proxy_class_name;
1151
1152         mono_g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
1153
1154         return rc;
1155 }
1156
1157 gpointer
1158 mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *rp)
1159 {
1160         mono_domain_lock (domain);
1161         if (rp->target_domain_id != -1) {
1162                 if (remote_class->xdomain_vtable == NULL)
1163                         remote_class->xdomain_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_APPDOMAIN);
1164                 mono_domain_unlock (domain);
1165                 return remote_class->xdomain_vtable;
1166         }
1167         if (remote_class->default_vtable == NULL)
1168                 remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN);
1169         
1170         mono_domain_unlock (domain);
1171         return remote_class->default_vtable;
1172 }
1173
1174 /**
1175  * mono_upgrade_remote_class:
1176  * @domain: the application domain
1177  * @tproxy: the proxy whose remote class has to be upgraded.
1178  * @klass: class to which the remote class can be casted.
1179  *
1180  * Updates the vtable of the remote class by adding the necessary method slots
1181  * and interface offsets so it can be safely casted to klass. klass can be a
1182  * class or an interface.
1183  */
1184 void
1185 mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoClass *klass)
1186 {
1187         MonoTransparentProxy *tproxy;
1188         MonoRemoteClass *remote_class;
1189         gboolean redo_vtable;
1190
1191         mono_domain_lock (domain);
1192
1193         tproxy = (MonoTransparentProxy*) proxy_object;
1194         remote_class = tproxy->remote_class;
1195         
1196         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1197                 int i;
1198                 redo_vtable = TRUE;
1199                 for (i = 0; i < remote_class->interface_count && redo_vtable; i++)
1200                         if (remote_class->interfaces [i] == klass)
1201                                 redo_vtable = FALSE;
1202         }
1203         else {
1204                 redo_vtable = (remote_class->proxy_class != klass);
1205         }
1206
1207         if (redo_vtable) {
1208                 tproxy->remote_class = clone_remote_class (domain, remote_class, klass);
1209                 proxy_object->vtable = mono_remote_class_vtable (domain, tproxy->remote_class, tproxy->rp);
1210         }
1211         
1212         mono_domain_unlock (domain);
1213 }
1214
1215
1216 /**
1217  * mono_object_get_virtual_method:
1218  * @obj: object to operate on.
1219  * @method: method 
1220  *
1221  * Retrieves the MonoMethod that would be called on obj if obj is passed as
1222  * the instance of a callvirt of method.
1223  */
1224 MonoMethod*
1225 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method)
1226 {
1227         MonoClass *klass;
1228         MonoMethod **vtable;
1229         gboolean is_proxy;
1230         MonoMethod *res = NULL;
1231
1232         klass = mono_object_class (obj);
1233         if (klass == mono_defaults.transparent_proxy_class) {
1234                 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
1235                 is_proxy = TRUE;
1236         } else {
1237                 is_proxy = FALSE;
1238         }
1239
1240         if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
1241                         return method;
1242
1243         mono_class_setup_vtable (klass);
1244         vtable = klass->vtable;
1245
1246         /* check method->slot is a valid index: perform isinstance? */
1247         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1248                 if (!is_proxy)
1249                         res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
1250         } else {
1251                 if (method->slot != -1)
1252                         res = vtable [method->slot];
1253         }
1254
1255         if (is_proxy) {
1256                 if (!res) res = method;   /* It may be an interface or abstract class method */
1257                 res = mono_marshal_get_remoting_invoke (res);
1258         }
1259
1260         g_assert (res);
1261         
1262         return res;
1263 }
1264
1265 static MonoObject*
1266 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1267 {
1268         g_error ("runtime invoke called on uninitialized runtime");
1269         return NULL;
1270 }
1271
1272 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
1273
1274 /**
1275  * mono_runtime_invoke:
1276  * @method: method to invoke
1277  * @obJ: object instance
1278  * @params: arguments to the method
1279  * @exc: exception information.
1280  *
1281  * Invokes the method represented by @method on the object @obj.
1282  *
1283  * obj is the 'this' pointer, it should be NULL for static
1284  * methods, a MonoObject* for object instances and a pointer to
1285  * the value type for value types.
1286  *
1287  * The params array contains the arguments to the method with the
1288  * same convention: MonoObject* pointers for object instances and
1289  * pointers to the value type otherwise. 
1290  * 
1291  * From unmanaged code you'll usually use the
1292  * mono_runtime_invoke() variant.
1293  *
1294  * Note that this function doesn't handle virtual methods for
1295  * you, it will exec the exact method you pass: we still need to
1296  * expose a function to lookup the derived class implementation
1297  * of a virtual method (there are examples of this in the code,
1298  * though).
1299  * 
1300  * You can pass NULL as the exc argument if you don't want to
1301  * catch exceptions, otherwise, *exc will be set to the exception
1302  * thrown, if any.  if an exception is thrown, you can't use the
1303  * MonoObject* result from the function.
1304  * 
1305  * If the method returns a value type, it is boxed in an object
1306  * reference.
1307  */
1308 MonoObject*
1309 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1310 {
1311         return default_mono_runtime_invoke (method, obj, params, exc);
1312 }
1313
1314 static void
1315 set_value (MonoType *type, void *dest, void *value, int deref_pointer)
1316 {
1317         int t;
1318         if (type->byref) {
1319                 gpointer *p = (gpointer*)dest;
1320                 *p = value;
1321                 return;
1322         }
1323         t = type->type;
1324 handle_enum:
1325         switch (t) {
1326         case MONO_TYPE_BOOLEAN:
1327         case MONO_TYPE_I1:
1328         case MONO_TYPE_U1: {
1329                 guint8 *p = (guint8*)dest;
1330                 *p = value ? *(guint8*)value : 0;
1331                 return;
1332         }
1333         case MONO_TYPE_I2:
1334         case MONO_TYPE_U2:
1335         case MONO_TYPE_CHAR: {
1336                 guint16 *p = (guint16*)dest;
1337                 *p = value ? *(guint16*)value : 0;
1338                 return;
1339         }
1340 #if SIZEOF_VOID_P == 4
1341         case MONO_TYPE_I:
1342         case MONO_TYPE_U:
1343 #endif
1344         case MONO_TYPE_I4:
1345         case MONO_TYPE_U4: {
1346                 gint32 *p = (gint32*)dest;
1347                 *p = value ? *(gint32*)value : 0;
1348                 return;
1349         }
1350 #if SIZEOF_VOID_P == 8
1351         case MONO_TYPE_I:
1352         case MONO_TYPE_U:
1353 #endif
1354         case MONO_TYPE_I8:
1355         case MONO_TYPE_U8: {
1356                 gint64 *p = (gint64*)dest;
1357                 *p = value ? *(gint64*)value : 0;
1358                 return;
1359         }
1360         case MONO_TYPE_R4: {
1361                 float *p = (float*)dest;
1362                 *p = value ? *(float*)value : 0;
1363                 return;
1364         }
1365         case MONO_TYPE_R8: {
1366                 double *p = (double*)dest;
1367                 *p = value ? *(double*)value : 0;
1368                 return;
1369         }
1370         case MONO_TYPE_STRING:
1371         case MONO_TYPE_SZARRAY:
1372         case MONO_TYPE_CLASS:
1373         case MONO_TYPE_OBJECT:
1374         case MONO_TYPE_ARRAY:
1375         case MONO_TYPE_PTR: {
1376                 gpointer *p = (gpointer*)dest;
1377                 *p = deref_pointer? *(gpointer*)value: value;
1378                 return;
1379         }
1380         case MONO_TYPE_VALUETYPE:
1381                 if (type->data.klass->enumtype) {
1382                         t = type->data.klass->enum_basetype->type;
1383                         goto handle_enum;
1384                 } else {
1385                         int size;
1386                         size = mono_class_value_size (type->data.klass, NULL);
1387                         if (value == NULL)
1388                                 memset (dest, 0, size);
1389                         else
1390                                 memcpy (dest, value, size);
1391                 }
1392                 return;
1393         case MONO_TYPE_GENERICINST:
1394                 t = type->data.generic_class->container_class->byval_arg.type;
1395                 goto handle_enum;
1396         default:
1397                 g_warning ("got type %x", type->type);
1398                 g_assert_not_reached ();
1399         }
1400 }
1401
1402 /**
1403  * mono_field_set_value:
1404  * @obj: Instance object
1405  * @field: MonoClassField describing the field to set
1406  * @value: The value to be set
1407  *
1408  * Sets the value of the field described by @field in the object instance @obj
1409  * to the value passed in @value.
1410  *
1411  * The value must be on the native format of the field type. 
1412  */
1413 void
1414 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
1415 {
1416         void *dest;
1417
1418         g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1419
1420         dest = (char*)obj + field->offset;
1421         set_value (field->type, dest, value, FALSE);
1422 }
1423
1424 /**
1425  * mono_field_static_set_value:
1426  * @field: MonoClassField describing the field to set
1427  * @value: The value to be set
1428  *
1429  * Sets the value of the static field described by @field
1430  * to the value passed in @value.
1431  *
1432  * The value must be on the native format of the field type. 
1433  */
1434 void
1435 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
1436 {
1437         void *dest;
1438
1439         g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1440         /* you cant set a constant! */
1441         g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
1442         
1443         dest = (char*)vt->data + field->offset;
1444         set_value (field->type, dest, value, FALSE);
1445 }
1446
1447 /**
1448  * mono_field_get_value:
1449  * @obj: Object instance
1450  * @field: MonoClassField describing the field to fetch information from
1451  * @value: pointer to the location where the value will be stored
1452  *
1453  * Use this routine to get the value of the field @field in the object
1454  * passed.
1455  *
1456  * The pointer provided by value must be of the field type, for reference
1457  * types this is a MonoObject*, for value types its the actual pointer to
1458  * the value type.
1459  *
1460  * For example:
1461  *     int i;
1462  *     mono_field_get_value (obj, int_field, &i);
1463  */
1464 void
1465 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
1466 {
1467         void *src;
1468
1469         g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1470
1471         src = (char*)obj + field->offset;
1472         set_value (field->type, value, src, TRUE);
1473 }
1474
1475 /**
1476  * mono_field_get_value_object:
1477  * @domain: domain where the object will be created (if boxing)
1478  * @field: MonoClassField describing the field to fetch information from
1479  * @obj: The object instance for the field.
1480  *
1481  * Returns: a new MonoObject with the value from the given field.  If the
1482  * field represents a value type, the value is boxed.
1483  *
1484  */
1485 MonoObject *
1486 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
1487 {       
1488         MonoObject *o;
1489         MonoClass *klass;
1490         MonoVTable *vtable = NULL;
1491         gchar *v;
1492         gboolean is_static = FALSE;
1493         gboolean is_ref = FALSE;
1494
1495         switch (field->type->type) {
1496         case MONO_TYPE_STRING:
1497         case MONO_TYPE_OBJECT:
1498         case MONO_TYPE_CLASS:
1499         case MONO_TYPE_ARRAY:
1500         case MONO_TYPE_SZARRAY:
1501                 is_ref = TRUE;
1502                 break;
1503         case MONO_TYPE_U1:
1504         case MONO_TYPE_I1:
1505         case MONO_TYPE_BOOLEAN:
1506         case MONO_TYPE_U2:
1507         case MONO_TYPE_I2:
1508         case MONO_TYPE_CHAR:
1509         case MONO_TYPE_U:
1510         case MONO_TYPE_I:
1511         case MONO_TYPE_U4:
1512         case MONO_TYPE_I4:
1513         case MONO_TYPE_R4:
1514         case MONO_TYPE_U8:
1515         case MONO_TYPE_I8:
1516         case MONO_TYPE_R8:
1517         case MONO_TYPE_VALUETYPE:
1518                 is_ref = field->type->byref;
1519                 break;
1520         default:
1521                 g_error ("type 0x%x not handled in "
1522                          "mono_field_get_value_object", field->type->type);
1523                 return NULL;
1524         }
1525
1526         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1527                 is_static = TRUE;
1528                 vtable = mono_class_vtable (domain, field->parent);
1529                 if (!vtable->initialized)
1530                         mono_runtime_class_init (vtable);
1531         }
1532         
1533         if (is_ref) {
1534                 if (is_static) {
1535                         mono_field_static_get_value (vtable, field, &o);
1536                 } else {
1537                         mono_field_get_value (obj, field, &o);
1538                 }
1539                 return o;
1540         }
1541
1542         /* boxed value type */
1543         klass = mono_class_from_mono_type (field->type);
1544         o = mono_object_new (domain, klass);
1545         v = ((gchar *) o) + sizeof (MonoObject);
1546         if (is_static) {
1547                 mono_field_static_get_value (vtable, field, v);
1548         } else {
1549                 mono_field_get_value (obj, field, v);
1550         }
1551
1552         return o;
1553 }
1554
1555 int
1556 mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, const char *blob, void *value)
1557 {
1558         int retval = 0;
1559         const char *p = blob;
1560         mono_metadata_decode_blob_size (p, &p);
1561
1562         switch (type) {
1563         case MONO_TYPE_BOOLEAN:
1564         case MONO_TYPE_U1:
1565         case MONO_TYPE_I1:
1566                 *(guint8 *) value = *p;
1567                 break;
1568         case MONO_TYPE_CHAR:
1569         case MONO_TYPE_U2:
1570         case MONO_TYPE_I2:
1571                 *(guint16*) value = read16 (p);
1572                 break;
1573         case MONO_TYPE_U4:
1574         case MONO_TYPE_I4:
1575                 *(guint32*) value = read32 (p);
1576                 break;
1577         case MONO_TYPE_U8:
1578         case MONO_TYPE_I8:
1579                 *(guint64*) value = read64 (p);
1580                 break;
1581         case MONO_TYPE_R4:
1582                 readr4 (p, (float*) value);
1583                 break;
1584         case MONO_TYPE_R8:
1585                 readr8 (p, (double*) value);
1586                 break;
1587         case MONO_TYPE_STRING:
1588                 *(gpointer*) value = mono_ldstr_metdata_sig (domain, blob);
1589                 break;
1590         case MONO_TYPE_CLASS:
1591                 *(gpointer*) value = NULL;
1592                 break;
1593         default:
1594                 retval = -1;
1595                 g_warning ("type 0x%02x should not be in constant table", type);
1596         }
1597         return retval;
1598 }
1599
1600 static void
1601 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
1602 {
1603         g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
1604         mono_get_constant_value_from_blob (domain, field->def_type, field->data, value);
1605 }
1606
1607 /**
1608  * mono_field_static_get_value:
1609  * @vt: vtable to the object
1610  * @field: MonoClassField describing the field to fetch information from
1611  * @value: where the value is returned
1612  *
1613  * Use this routine to get the value of the static field @field value.
1614  *
1615  * The pointer provided by value must be of the field type, for reference
1616  * types this is a MonoObject*, for value types its the actual pointer to
1617  * the value type.
1618  *
1619  * For example:
1620  *     int i;
1621  *     mono_field_static_get_value (vt, int_field, &i);
1622  */
1623 void
1624 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1625 {
1626         void *src;
1627
1628         g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1629         
1630         if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
1631                 get_default_field_value (vt->domain, field, value);
1632                 return;
1633         }
1634
1635         src = (char*)vt->data + field->offset;
1636         set_value (field->type, value, src, TRUE);
1637 }
1638
1639 /**
1640  * mono_property_set_value:
1641  * @prop: MonoProperty to set
1642  * @obj: instance object on which to act
1643  * @params: parameters to pass to the propery
1644  * @exc: optional exception
1645  *
1646  * Invokes the property's set method with the given arguments on the
1647  * object instance obj (or NULL for static properties). 
1648  * 
1649  * You can pass NULL as the exc argument if you don't want to
1650  * catch exceptions, otherwise, *exc will be set to the exception
1651  * thrown, if any.  if an exception is thrown, you can't use the
1652  * MonoObject* result from the function.
1653  */
1654 void
1655 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1656 {
1657         default_mono_runtime_invoke (prop->set, obj, params, exc);
1658 }
1659
1660 /**
1661  * mono_property_get_value:
1662  * @prop: MonoProperty to fetch
1663  * @obj: instance object on which to act
1664  * @params: parameters to pass to the propery
1665  * @exc: optional exception
1666  *
1667  * Invokes the property's get method with the given arguments on the
1668  * object instance obj (or NULL for static properties). 
1669  * 
1670  * You can pass NULL as the exc argument if you don't want to
1671  * catch exceptions, otherwise, *exc will be set to the exception
1672  * thrown, if any.  if an exception is thrown, you can't use the
1673  * MonoObject* result from the function.
1674  *
1675  * Returns: the value from invoking the get method on the property.
1676  */
1677 MonoObject*
1678 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1679 {
1680         return default_mono_runtime_invoke (prop->get, obj, params, exc);
1681 }
1682
1683
1684 /**
1685  * mono_get_delegate_invoke:
1686  * @klass: The delegate class
1687  *
1688  * Returns: the MonoMethod for the "Invoke" method in the delegate klass
1689  */
1690 MonoMethod *
1691 mono_get_delegate_invoke (MonoClass *klass)
1692 {
1693         MonoMethod *im;
1694
1695         im = mono_class_get_method_from_name (klass, "Invoke", -1);
1696         g_assert (im);
1697
1698         return im;
1699 }
1700
1701 /**
1702  * mono_runtime_delegate_invoke:
1703  * @delegate: pointer to a delegate object.
1704  * @params: parameters for the delegate.
1705  * @exc: Pointer to the exception result.
1706  *
1707  * Invokes the delegate method @delegate with the parameters provided.
1708  *
1709  * You can pass NULL as the exc argument if you don't want to
1710  * catch exceptions, otherwise, *exc will be set to the exception
1711  * thrown, if any.  if an exception is thrown, you can't use the
1712  * MonoObject* result from the function.
1713  */
1714 MonoObject*
1715 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1716 {
1717         MonoMethod *im;
1718
1719         im = mono_get_delegate_invoke (delegate->vtable->klass);
1720         g_assert (im);
1721
1722         return mono_runtime_invoke (im, delegate, params, exc);
1723 }
1724
1725 static char **main_args = NULL;
1726 static int num_main_args;
1727
1728 /**
1729  * mono_runtime_get_main_args:
1730  *
1731  * Returns: a MonoArray with the arguments passed to the main program
1732  */
1733 MonoArray*
1734 mono_runtime_get_main_args (void)
1735 {
1736         MonoArray *res;
1737         int i;
1738         MonoDomain *domain = mono_domain_get ();
1739
1740         if (!main_args)
1741                 return NULL;
1742
1743         res = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, num_main_args);
1744
1745         for (i = 0; i < num_main_args; ++i)
1746                 mono_array_set (res, gpointer, i, mono_string_new (domain, main_args [i]));
1747
1748         return res;
1749 }
1750
1751 static void
1752 fire_process_exit_event (void)
1753 {
1754         MonoClassField *field;
1755         MonoDomain *domain = mono_domain_get ();
1756         gpointer pa [2];
1757         MonoObject *delegate, *exc;
1758         
1759         field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1760         g_assert (field);
1761
1762         if (domain != mono_get_root_domain ())
1763                 return;
1764
1765         delegate = *(MonoObject **)(((char *)domain->domain) + field->offset); 
1766         if (delegate == NULL)
1767                 return;
1768
1769         pa [0] = domain;
1770         pa [1] = NULL;
1771         mono_runtime_delegate_invoke (delegate, pa, &exc);
1772 }
1773
1774 /**
1775  * mono_runtime_run_main:
1776  * @method: the method to start the application with (usually Main)
1777  * @argc: number of arguments from the command line
1778  * @argv: array of strings from the command line
1779  * @exc: excetption results
1780  *
1781  * Execute a standard Main() method (argc/argv contains the
1782  * executable name). This method also sets the command line argument value
1783  * needed by System.Environment.
1784  *
1785  * 
1786  */
1787 int
1788 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1789                        MonoObject **exc)
1790 {
1791         int i;
1792         MonoArray *args = NULL;
1793         MonoDomain *domain = mono_domain_get ();
1794         gchar *utf8_fullpath;
1795         int result;
1796
1797         mono_thread_set_main (mono_thread_current ());
1798
1799         main_args = g_new0 (char*, argc);
1800         num_main_args = argc;
1801
1802         if (!g_path_is_absolute (argv [0])) {
1803                 gchar *basename = g_path_get_basename (argv [0]);
1804                 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1805                                                     basename,
1806                                                     NULL);
1807
1808                 utf8_fullpath = mono_utf8_from_external (fullpath);
1809                 if(utf8_fullpath == NULL) {
1810                         /* Printing the arg text will cause glib to
1811                          * whinge about "Invalid UTF-8", but at least
1812                          * its relevant, and shows the problem text
1813                          * string.
1814                          */
1815                         g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1816                         g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1817                         exit (-1);
1818                 }
1819
1820                 g_free (fullpath);
1821                 g_free (basename);
1822         } else {
1823                 utf8_fullpath = mono_utf8_from_external (argv[0]);
1824                 if(utf8_fullpath == NULL) {
1825                         g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1826                         g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1827                         exit (-1);
1828                 }
1829         }
1830
1831         main_args [0] = utf8_fullpath;
1832
1833         for (i = 1; i < argc; ++i) {
1834                 gchar *utf8_arg;
1835
1836                 utf8_arg=mono_utf8_from_external (argv[i]);
1837                 if(utf8_arg==NULL) {
1838                         /* Ditto the comment about Invalid UTF-8 here */
1839                         g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1840                         g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1841                         exit (-1);
1842                 }
1843
1844                 main_args [i] = utf8_arg;
1845         }
1846         argc--;
1847         argv++;
1848         if (mono_method_signature (method)->param_count) {
1849                 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1850                 for (i = 0; i < argc; ++i) {
1851                         /* The encodings should all work, given that
1852                          * we've checked all these args for the
1853                          * main_args array.
1854                          */
1855                         gchar *str = mono_utf8_from_external (argv [i]);
1856                         MonoString *arg = mono_string_new (domain, str);
1857                         mono_array_set (args, gpointer, i, arg);
1858                         g_free (str);
1859                 }
1860         } else {
1861                 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1862         }
1863         
1864         mono_assembly_set_main (method->klass->image->assembly);
1865
1866         result = mono_runtime_exec_main (method, args, exc);
1867         fire_process_exit_event ();
1868         return result;
1869 }
1870
1871 /* Used in mono_unhandled_exception */
1872 static MonoObject *
1873 create_unhandled_exception_eventargs (MonoObject *exc)
1874 {
1875         MonoClass *klass;
1876         gpointer args [2];
1877         MonoMethod *method = NULL;
1878         MonoBoolean is_terminating = TRUE;
1879         MonoObject *obj;
1880
1881         klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1882         g_assert (klass);
1883
1884         mono_class_init (klass);
1885
1886         /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1887         method = mono_class_get_method_from_name_flags (klass, ".ctor", 2, METHOD_ATTRIBUTE_PUBLIC);
1888         g_assert (method);
1889
1890         args [0] = exc;
1891         args [1] = &is_terminating;
1892
1893         obj = mono_object_new (mono_domain_get (), klass);
1894         mono_runtime_invoke (method, obj, args, NULL);
1895
1896         return obj;
1897 }
1898
1899 /**
1900  * mono_unhandled_exception:
1901  * @exc: exception thrown
1902  *
1903  * This is a VM internal routine.
1904  *
1905  * We call this function when we detect an unhandled exception
1906  * in the default domain.
1907  *
1908  * It invokes the * UnhandledException event in AppDomain or prints
1909  * a warning to the console 
1910  */
1911 void
1912 mono_unhandled_exception (MonoObject *exc)
1913 {
1914         MonoDomain *domain = mono_domain_get ();
1915         MonoClassField *field;
1916         MonoObject *delegate;
1917
1918         field=mono_class_get_field_from_name(mono_defaults.appdomain_class, 
1919                                              "UnhandledException");
1920         g_assert (field);
1921
1922         if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1923                 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset); 
1924
1925                 /* set exitcode only in the main thread */
1926                 if (mono_thread_current () == main_thread)
1927                         mono_environment_exitcode_set (1);
1928                 if (domain != mono_get_root_domain () || !delegate) {
1929                         mono_print_unhandled_exception (exc);
1930                 } else {
1931                         MonoObject *e = NULL;
1932                         gpointer pa [2];
1933
1934                         pa [0] = domain->domain;
1935                         pa [1] = create_unhandled_exception_eventargs (exc);
1936                         mono_runtime_delegate_invoke (delegate, pa, &e);
1937                         
1938                         if (e) {
1939                                 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1940                                 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1941                                 g_free (msg);
1942                         }
1943                 }
1944         }
1945 }
1946
1947 /*
1948  * Launch a new thread to execute a function
1949  *
1950  * main_func is called back from the thread with main_args as the
1951  * parameter.  The callback function is expected to start Main()
1952  * eventually.  This function then waits for all managed threads to
1953  * finish.
1954  * It is not necesseray anymore to execute managed code in a subthread,
1955  * so this function should not be used anymore by default: just
1956  * execute the code and then call mono_thread_manage ().
1957  */
1958 void
1959 mono_runtime_exec_managed_code (MonoDomain *domain,
1960                                 MonoMainThreadFunc main_func,
1961                                 gpointer main_args)
1962 {
1963         mono_thread_create (domain, main_func, main_args);
1964
1965         mono_thread_manage ();
1966 }
1967
1968 /*
1969  * Execute a standard Main() method (args doesn't contain the
1970  * executable name).
1971  */
1972 int
1973 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1974 {
1975         MonoDomain *domain;
1976         gpointer pa [1];
1977         int rval;
1978
1979         g_assert (args);
1980
1981         pa [0] = args;
1982
1983         domain = mono_object_domain (args);
1984         if (!domain->entry_assembly) {
1985                 gchar *str;
1986                 MonoAssembly *assembly;
1987
1988                 assembly = method->klass->image->assembly;
1989                 domain->entry_assembly = assembly;
1990                 domain->setup->application_base = mono_string_new (domain, assembly->basedir);
1991
1992                 str = g_strconcat (assembly->image->name, ".config", NULL);
1993                 domain->setup->configuration_file = mono_string_new (domain, str);
1994                 g_free (str);
1995         }
1996
1997         /* FIXME: check signature of method */
1998         if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
1999                 MonoObject *res;
2000                 res = mono_runtime_invoke (method, NULL, pa, exc);
2001                 if (!exc || !*exc)
2002                         rval = *(guint32 *)((char *)res + sizeof (MonoObject));
2003                 else
2004                         rval = -1;
2005
2006                 mono_environment_exitcode_set (rval);
2007         } else {
2008                 mono_runtime_invoke (method, NULL, pa, exc);
2009                 if (!exc || !*exc)
2010                         rval = 0;
2011                 else {
2012                         /* If the return type of Main is void, only
2013                          * set the exitcode if an exception was thrown
2014                          * (we don't want to blow away an
2015                          * explicitly-set exit code)
2016                          */
2017                         rval = -1;
2018                         mono_environment_exitcode_set (rval);
2019                 }
2020         }
2021
2022         return rval;
2023 }
2024
2025 /**
2026  * mono_install_runtime_invoke:
2027  * @func: Function to install
2028  *
2029  * This is a VM internal routine
2030  */
2031 void
2032 mono_install_runtime_invoke (MonoInvokeFunc func)
2033 {
2034         default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
2035 }
2036
2037 /**
2038  * mono_runtime_invoke_array:
2039  * @method: method to invoke
2040  * @obJ: object instance
2041  * @params: arguments to the method
2042  * @exc: exception information.
2043  *
2044  * Invokes the method represented by @method on the object @obj.
2045  *
2046  * obj is the 'this' pointer, it should be NULL for static
2047  * methods, a MonoObject* for object instances and a pointer to
2048  * the value type for value types.
2049  *
2050  * The params array contains the arguments to the method with the
2051  * same convention: MonoObject* pointers for object instances and
2052  * pointers to the value type otherwise. The _invoke_array
2053  * variant takes a C# object[] as the params argument (MonoArray
2054  * *params): in this case the value types are boxed inside the
2055  * respective reference representation.
2056  * 
2057  * From unmanaged code you'll usually use the
2058  * mono_runtime_invoke() variant.
2059  *
2060  * Note that this function doesn't handle virtual methods for
2061  * you, it will exec the exact method you pass: we still need to
2062  * expose a function to lookup the derived class implementation
2063  * of a virtual method (there are examples of this in the code,
2064  * though).
2065  * 
2066  * You can pass NULL as the exc argument if you don't want to
2067  * catch exceptions, otherwise, *exc will be set to the exception
2068  * thrown, if any.  if an exception is thrown, you can't use the
2069  * MonoObject* result from the function.
2070  * 
2071  * If the method returns a value type, it is boxed in an object
2072  * reference.
2073  */
2074 MonoObject*
2075 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
2076                            MonoObject **exc)
2077 {
2078         MonoMethodSignature *sig = mono_method_signature (method);
2079         gpointer *pa = NULL;
2080         int i;
2081                 
2082         if (NULL != params) {
2083                 pa = alloca (sizeof (gpointer) * mono_array_length (params));
2084                 for (i = 0; i < mono_array_length (params); i++) {
2085                         if (sig->params [i]->byref) {
2086                                 /* nothing to do */
2087                         }
2088
2089                         switch (sig->params [i]->type) {
2090                         case MONO_TYPE_U1:
2091                         case MONO_TYPE_I1:
2092                         case MONO_TYPE_BOOLEAN:
2093                         case MONO_TYPE_U2:
2094                         case MONO_TYPE_I2:
2095                         case MONO_TYPE_CHAR:
2096                         case MONO_TYPE_U:
2097                         case MONO_TYPE_I:
2098                         case MONO_TYPE_U4:
2099                         case MONO_TYPE_I4:
2100                         case MONO_TYPE_U8:
2101                         case MONO_TYPE_I8:
2102                         case MONO_TYPE_R4:
2103                         case MONO_TYPE_R8:
2104                         case MONO_TYPE_VALUETYPE:
2105                                 /* MS seems to create the objects if a null is passed in */
2106                                 if (! ((gpointer *)params->vector)[i])
2107                                         ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
2108                                 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
2109                                 break;
2110                         case MONO_TYPE_STRING:
2111                         case MONO_TYPE_OBJECT:
2112                         case MONO_TYPE_CLASS:
2113                         case MONO_TYPE_ARRAY:
2114                         case MONO_TYPE_SZARRAY:
2115                                 if (sig->params [i]->byref)
2116                                         pa [i] = &(((gpointer *)params->vector)[i]);
2117                                 else
2118                                         pa [i] = (char *)(((gpointer *)params->vector)[i]);
2119                                 break;
2120                         default:
2121                                 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
2122                         }
2123                 }
2124         }
2125
2126         if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
2127                 void *o = obj;
2128                 if (!obj) {
2129                         obj = mono_object_new (mono_domain_get (), method->klass);
2130                         if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
2131                                 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
2132                         }
2133                         if (method->klass->valuetype)
2134                                 o = mono_object_unbox (obj);
2135                         else
2136                                 o = obj;
2137                 }
2138                 else if (method->klass->valuetype)
2139                         obj = mono_value_box (mono_domain_get (), method->klass, obj);
2140
2141                 mono_runtime_invoke (method, o, pa, exc);
2142                 return obj;
2143         } else {
2144                 /* obj must be already unboxed if needed */
2145                 return mono_runtime_invoke (method, obj, pa, exc);
2146         }
2147 }
2148
2149 static void
2150 arith_overflow (void)
2151 {
2152         mono_raise_exception (mono_get_exception_overflow ());
2153 }
2154
2155 /**
2156  * mono_object_allocate:
2157  * @size: number of bytes to allocate
2158  *
2159  * This is a very simplistic routine until we have our GC-aware
2160  * memory allocator. 
2161  *
2162  * Returns: an allocated object of size @size, or NULL on failure.
2163  */
2164 static inline void *
2165 mono_object_allocate (size_t size, MonoVTable *vtable)
2166 {
2167         MonoObject *o;
2168         mono_stats.new_object_count++;
2169         ALLOC_OBJECT (o, vtable, size);
2170
2171         return o;
2172 }
2173
2174 /**
2175  * mono_object_allocate_ptrfree:
2176  * @size: number of bytes to allocate
2177  *
2178  * Note that the memory allocated is not zeroed.
2179  * Returns: an allocated object of size @size, or NULL on failure.
2180  */
2181 static inline void *
2182 mono_object_allocate_ptrfree (size_t size, MonoVTable *vtable)
2183 {
2184         MonoObject *o;
2185         mono_stats.new_object_count++;
2186         ALLOC_PTRFREE (o, vtable, size);
2187         return o;
2188 }
2189
2190 static inline void *
2191 mono_object_allocate_spec (size_t size, MonoVTable *vtable)
2192 {
2193         void *o;
2194         ALLOC_TYPED (o, size, vtable);
2195         mono_stats.new_object_count++;
2196
2197         return o;
2198 }
2199
2200 /**
2201  * mono_object_new:
2202  * @klass: the class of the object that we want to create
2203  *
2204  * Returns: a newly created object whose definition is
2205  * looked up using @klass.   This will not invoke any constructors, 
2206  * so the consumer of this routine has to invoke any constructors on
2207  * its own to initialize the object.
2208  */
2209 MonoObject *
2210 mono_object_new (MonoDomain *domain, MonoClass *klass)
2211 {
2212         MONO_ARCH_SAVE_REGS;
2213         return mono_object_new_specific (mono_class_vtable (domain, klass));
2214 }
2215
2216 /**
2217  * mono_object_new_specific:
2218  * @vtable: the vtable of the object that we want to create
2219  *
2220  * Returns: A newly created object with class and domain specified
2221  * by @vtable
2222  */
2223 MonoObject *
2224 mono_object_new_specific (MonoVTable *vtable)
2225 {
2226         MonoObject *o;
2227
2228         MONO_ARCH_SAVE_REGS;
2229         
2230         if (vtable->remote)
2231         {
2232                 gpointer pa [1];
2233                 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
2234
2235                 if (im == NULL) {
2236                         MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
2237
2238                         if (!klass->inited)
2239                                 mono_class_init (klass);
2240
2241                         im = mono_class_get_method_from_name (klass, "CreateProxyForType", 1);
2242                         g_assert (im);
2243                         vtable->domain->create_proxy_for_type_method = im;
2244                 }
2245         
2246                 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
2247
2248                 o = mono_runtime_invoke (im, NULL, pa, NULL);           
2249                 if (o != NULL) return o;
2250         }
2251
2252         return mono_object_new_alloc_specific (vtable);
2253 }
2254
2255 MonoObject *
2256 mono_object_new_alloc_specific (MonoVTable *vtable)
2257 {
2258         MonoObject *o;
2259
2260         if (!vtable->klass->has_references) {
2261                 o = mono_object_new_ptrfree (vtable);
2262         } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2263                 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
2264         } else {
2265 /*              printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2266                 o = mono_object_allocate (vtable->klass->instance_size, vtable);
2267         }
2268         if (vtable->klass->has_finalize)
2269                 mono_object_register_finalizer (o);
2270         
2271         mono_profiler_allocation (o, vtable->klass);
2272         return o;
2273 }
2274
2275 MonoObject*
2276 mono_object_new_fast (MonoVTable *vtable)
2277 {
2278         MonoObject *o;
2279         ALLOC_TYPED (o, vtable->klass->instance_size, vtable);
2280         return o;
2281 }
2282
2283 static MonoObject*
2284 mono_object_new_ptrfree (MonoVTable *vtable)
2285 {
2286         MonoObject *obj;
2287         ALLOC_PTRFREE (obj, vtable, vtable->klass->instance_size);
2288 #if NEED_TO_ZERO_PTRFREE
2289         /* an inline memset is much faster for the common vcase of small objects
2290          * note we assume the allocated size is a multiple of sizeof (void*).
2291          */
2292         if (vtable->klass->instance_size < 128) {
2293                 gpointer *p, *end;
2294                 end = (gpointer*)((char*)obj + vtable->klass->instance_size);
2295                 p = (gpointer*)((char*)obj + sizeof (MonoObject));
2296                 while (p < end) {
2297                         *p = NULL;
2298                         ++p;
2299                 }
2300         } else {
2301                 memset ((char*)obj + sizeof (MonoObject), 0, vtable->klass->instance_size - sizeof (MonoObject));
2302         }
2303 #endif
2304         return obj;
2305 }
2306
2307 static MonoObject*
2308 mono_object_new_ptrfree_box (MonoVTable *vtable)
2309 {
2310         MonoObject *obj;
2311         ALLOC_PTRFREE (obj, vtable, vtable->klass->instance_size);
2312         /* the object will be boxed right away, no need to memzero it */
2313         return obj;
2314 }
2315
2316 /**
2317  * mono_class_get_allocation_ftn:
2318  * @vtable: vtable
2319  * @for_box: the object will be used for boxing
2320  * @pass_size_in_words: 
2321  *
2322  * Return the allocation function appropriate for the given class.
2323  */
2324
2325 void*
2326 mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *pass_size_in_words)
2327 {
2328         *pass_size_in_words = FALSE;
2329
2330         if (vtable->klass->has_finalize || vtable->klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
2331                 return mono_object_new_specific;
2332
2333         if (!vtable->klass->has_references) {
2334                 //g_print ("ptrfree for %s.%s\n", vtable->klass->name_space, vtable->klass->name);
2335                 if (for_box)
2336                         return mono_object_new_ptrfree_box;
2337                 return mono_object_new_ptrfree;
2338         }
2339
2340         if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2341
2342                 return mono_object_new_fast;
2343
2344                 /* 
2345                  * FIXME: This is actually slower than mono_object_new_fast, because
2346                  * of the overhead of parameter passing.
2347                  */
2348                 /*
2349                 *pass_size_in_words = TRUE;
2350 #ifdef GC_REDIRECT_TO_LOCAL
2351                 return GC_local_gcj_fast_malloc;
2352 #else
2353                 return GC_gcj_fast_malloc;
2354 #endif
2355                 */
2356         }
2357
2358         return mono_object_new_specific;
2359 }
2360
2361 /**
2362  * mono_object_new_from_token:
2363  * @image: Context where the type_token is hosted
2364  * @token: a token of the type that we want to create
2365  *
2366  * Returns: A newly created object whose definition is
2367  * looked up using @token in the @image image
2368  */
2369 MonoObject *
2370 mono_object_new_from_token  (MonoDomain *domain, MonoImage *image, guint32 token)
2371 {
2372         MonoClass *class;
2373
2374         class = mono_class_get (image, token);
2375
2376         return mono_object_new (domain, class);
2377 }
2378
2379
2380 /**
2381  * mono_object_clone:
2382  * @obj: the object to clone
2383  *
2384  * Returns: A newly created object who is a shallow copy of @obj
2385  */
2386 MonoObject *
2387 mono_object_clone (MonoObject *obj)
2388 {
2389         MonoObject *o;
2390         int size;
2391
2392         size = obj->vtable->klass->instance_size;
2393         o = mono_object_allocate (size, obj->vtable);
2394         /* do not copy the sync state */
2395         memcpy ((char*)o + sizeof (MonoObject), (char*)obj + sizeof (MonoObject), size - sizeof (MonoObject));
2396         
2397         mono_profiler_allocation (o, obj->vtable->klass);
2398
2399         if (obj->vtable->klass->has_finalize)
2400                 mono_object_register_finalizer (o);
2401         return o;
2402 }
2403
2404 /**
2405  * mono_array_full_copy:
2406  * @src: source array to copy
2407  * @dest: destination array
2408  *
2409  * Copies the content of one array to another with exactly the same type and size.
2410  */
2411 void
2412 mono_array_full_copy (MonoArray *src, MonoArray *dest)
2413 {
2414         int size;
2415         MonoClass *klass = src->obj.vtable->klass;
2416
2417         MONO_ARCH_SAVE_REGS;
2418
2419         g_assert (klass == dest->obj.vtable->klass);
2420
2421         size = mono_array_length (src);
2422         g_assert (size == mono_array_length (dest));
2423         size *= mono_array_element_size (klass);
2424         memcpy (&dest->vector, &src->vector, size);
2425 }
2426
2427 /**
2428  * mono_array_clone_in_domain:
2429  * @domain: the domain in which the array will be cloned into
2430  * @array: the array to clone
2431  *
2432  * This routine returns a copy of the array that is hosted on the
2433  * specified MonoDomain.
2434  */
2435 MonoArray*
2436 mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
2437 {
2438         MonoArray *o;
2439         guint32 size, i;
2440         guint32 *sizes;
2441         MonoClass *klass = array->obj.vtable->klass;
2442
2443         MONO_ARCH_SAVE_REGS;
2444
2445         if (array->bounds == NULL) {
2446                 size = mono_array_length (array);
2447                 o = mono_array_new_full (domain, klass, &size, NULL);
2448
2449                 size *= mono_array_element_size (klass);
2450                 memcpy (&o->vector, &array->vector, size);
2451                 return o;
2452         }
2453         
2454         sizes = alloca (klass->rank * sizeof(guint32) * 2);
2455         size = mono_array_element_size (klass);
2456         for (i = 0; i < klass->rank; ++i) {
2457                 sizes [i] = array->bounds [i].length;
2458                 size *= array->bounds [i].length;
2459                 sizes [i + klass->rank] = array->bounds [i].lower_bound;
2460         }
2461         o = mono_array_new_full (domain, klass, sizes, sizes + klass->rank);
2462         memcpy (&o->vector, &array->vector, size);
2463
2464         return o;
2465 }
2466
2467 /**
2468  * mono_array_clone:
2469  * @array: the array to clone
2470  *
2471  * Returns: A newly created array who is a shallow copy of @array
2472  */
2473 MonoArray*
2474 mono_array_clone (MonoArray *array)
2475 {
2476         return mono_array_clone_in_domain (((MonoObject *)array)->vtable->domain, array);
2477 }
2478
2479 /* helper macros to check for overflow when calculating the size of arrays */
2480 #define MYGUINT32_MAX 4294967295U
2481 #define CHECK_ADD_OVERFLOW_UN(a,b) \
2482         (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
2483 #define CHECK_MUL_OVERFLOW_UN(a,b) \
2484         ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
2485         (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
2486
2487 /**
2488  * mono_array_new_full:
2489  * @domain: domain where the object is created
2490  * @array_class: array class
2491  * @lengths: lengths for each dimension in the array
2492  * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
2493  *
2494  * This routine creates a new array objects with the given dimensions,
2495  * lower bounds and type.
2496  */
2497 MonoArray*
2498 mono_array_new_full (MonoDomain *domain, MonoClass *array_class, 
2499                      guint32 *lengths, guint32 *lower_bounds)
2500 {
2501         guint32 byte_len, len, bounds_size;
2502         MonoObject *o;
2503         MonoArray *array;
2504         MonoVTable *vtable;
2505         int i;
2506
2507         if (!array_class->inited)
2508                 mono_class_init (array_class);
2509
2510         byte_len = mono_array_element_size (array_class);
2511         len = 1;
2512
2513         if (array_class->rank == 1 && array_class->byval_arg.type == MONO_TYPE_SZARRAY) {
2514                 len = lengths [0];
2515                 if ((int) len < 0)
2516                         arith_overflow ();
2517                 bounds_size = 0;
2518         } else {
2519                 bounds_size = sizeof (MonoArrayBounds) * array_class->rank;
2520
2521                 for (i = 0; i < array_class->rank; ++i) {
2522                         if ((int) lengths [i] < 0)
2523                                 arith_overflow ();
2524                         if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
2525                                 mono_gc_out_of_memory (MYGUINT32_MAX);
2526                         len *= lengths [i];
2527                 }
2528         }
2529
2530         if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
2531                 mono_gc_out_of_memory (MYGUINT32_MAX);
2532         byte_len *= len;
2533         if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2534                 mono_gc_out_of_memory (MYGUINT32_MAX);
2535         byte_len += sizeof (MonoArray);
2536         if (bounds_size) {
2537                 /* align */
2538                 if (CHECK_ADD_OVERFLOW_UN (byte_len, 3))
2539                         mono_gc_out_of_memory (MYGUINT32_MAX);
2540                 byte_len = (byte_len + 3) & ~3;
2541                 if (CHECK_ADD_OVERFLOW_UN (byte_len, bounds_size))
2542                         mono_gc_out_of_memory (MYGUINT32_MAX);
2543                 byte_len += bounds_size;
2544         }
2545         /* 
2546          * Following three lines almost taken from mono_object_new ():
2547          * they need to be kept in sync.
2548          */
2549         vtable = mono_class_vtable (domain, array_class);
2550         if (!array_class->has_references) {
2551                 o = mono_object_allocate_ptrfree (byte_len, vtable);
2552 #if NEED_TO_ZERO_PTRFREE
2553                 memset ((char*)o + sizeof (MonoObject), 0, byte_len - sizeof (MonoObject));
2554 #endif
2555         } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2556                 o = mono_object_allocate_spec (byte_len, vtable);
2557         }else {
2558                 o = mono_object_allocate (byte_len, vtable);
2559         }
2560
2561         array = (MonoArray*)o;
2562         array->max_length = len;
2563
2564         if (bounds_size) {
2565                 MonoArrayBounds *bounds = (MonoArrayBounds*)((char*)array + byte_len - bounds_size);
2566                 array->bounds = bounds;
2567                 for (i = 0; i < array_class->rank; ++i) {
2568                         bounds [i].length = lengths [i];
2569                         if (lower_bounds)
2570                                 bounds [i].lower_bound = lower_bounds [i];
2571                 }
2572         }
2573
2574         mono_profiler_allocation (o, array_class);
2575
2576         return array;
2577 }
2578
2579 /**
2580  * mono_array_new:
2581  * @domain: domain where the object is created
2582  * @eclass: element class
2583  * @n: number of array elements
2584  *
2585  * This routine creates a new szarray with @n elements of type @eclass.
2586  */
2587 MonoArray *
2588 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
2589 {
2590         MonoClass *ac;
2591
2592         MONO_ARCH_SAVE_REGS;
2593
2594         ac = mono_array_class_get (eclass, 1);
2595         g_assert (ac != NULL);
2596
2597         return mono_array_new_specific (mono_class_vtable (domain, ac), n);
2598 }
2599
2600 /**
2601  * mono_array_new_specific:
2602  * @vtable: a vtable in the appropriate domain for an initialized class
2603  * @n: number of array elements
2604  *
2605  * This routine is a fast alternative to mono_array_new() for code which
2606  * can be sure about the domain it operates in.
2607  */
2608 MonoArray *
2609 mono_array_new_specific (MonoVTable *vtable, guint32 n)
2610 {
2611         MonoObject *o;
2612         MonoArray *ao;
2613         guint32 byte_len, elem_size;
2614
2615         MONO_ARCH_SAVE_REGS;
2616
2617         if ((int) n < 0)
2618                 arith_overflow ();
2619         
2620         elem_size = mono_array_element_size (vtable->klass);
2621         if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
2622                 mono_gc_out_of_memory (MYGUINT32_MAX);
2623         byte_len = n * elem_size;
2624         if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2625                 mono_gc_out_of_memory (MYGUINT32_MAX);
2626         byte_len += sizeof (MonoArray);
2627         if (!vtable->klass->has_references) {
2628                 o = mono_object_allocate_ptrfree (byte_len, vtable);
2629 #if NEED_TO_ZERO_PTRFREE
2630                 memset ((char*)o + sizeof (MonoObject), 0, byte_len - sizeof (MonoObject));
2631 #endif
2632         } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2633                 o = mono_object_allocate_spec (byte_len, vtable);
2634         } else {
2635 /*              printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2636                 o = mono_object_allocate (byte_len, vtable);
2637         }
2638
2639         ao = (MonoArray *)o;
2640         ao->bounds = NULL;
2641         ao->max_length = n;
2642         mono_profiler_allocation (o, vtable->klass);
2643
2644         return ao;
2645 }
2646
2647 /**
2648  * mono_string_new_utf16:
2649  * @text: a pointer to an utf16 string
2650  * @len: the length of the string
2651  *
2652  * Returns: A newly created string object which contains @text.
2653  */
2654 MonoString *
2655 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
2656 {
2657         MonoString *s;
2658         
2659         s = mono_string_new_size (domain, len);
2660         g_assert (s != NULL);
2661
2662         memcpy (mono_string_chars (s), text, len * 2);
2663
2664         return s;
2665 }
2666
2667 /**
2668  * mono_string_new_size:
2669  * @text: a pointer to an utf16 string
2670  * @len: the length of the string
2671  *
2672  * Returns: A newly created string object of @len
2673  */
2674 MonoString *
2675 mono_string_new_size (MonoDomain *domain, gint32 len)
2676 {
2677         MonoString *s;
2678         MonoVTable *vtable;
2679         size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2680
2681         /* overflow ? can't fit it, can't allocate it! */
2682         if (len > size)
2683                 mono_gc_out_of_memory (-1);
2684
2685         vtable = mono_class_vtable (domain, mono_defaults.string_class);
2686
2687         s = mono_object_allocate_ptrfree (size, vtable);
2688
2689         s->length = len;
2690 #if NEED_TO_ZERO_PTRFREE
2691         s->chars [len] = 0;
2692 #endif
2693         mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2694
2695         return s;
2696 }
2697
2698 /**
2699  * mono_string_new_len:
2700  * @text: a pointer to an utf8 string
2701  * @length: number of bytes in @text to consider
2702  *
2703  * Returns: A newly created string object which contains @text.
2704  */
2705 MonoString*
2706 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2707 {
2708         GError *error = NULL;
2709         MonoString *o = NULL;
2710         guint16 *ut;
2711         glong items_written;
2712
2713         ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2714
2715         if (!error)
2716                 o = mono_string_new_utf16 (domain, ut, items_written);
2717         else 
2718                 g_error_free (error);
2719
2720         g_free (ut);
2721
2722         return o;
2723 }
2724
2725 /**
2726  * mono_string_new:
2727  * @text: a pointer to an utf8 string
2728  *
2729  * Returns: A newly created string object which contains @text.
2730  */
2731 MonoString*
2732 mono_string_new (MonoDomain *domain, const char *text)
2733 {
2734         GError *error = NULL;
2735         MonoString *o = NULL;
2736         guint16 *ut;
2737         glong items_written;
2738         int l;
2739
2740         l = strlen (text);
2741         
2742         ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2743
2744         if (!error)
2745                 o = mono_string_new_utf16 (domain, ut, items_written);
2746         else 
2747                 g_error_free (error);
2748
2749         g_free (ut);
2750
2751         return o;
2752 }
2753
2754 /**
2755  * mono_string_new_wrapper:
2756  * @text: pointer to utf8 characters.
2757  *
2758  * Helper function to create a string object from @text in the current domain.
2759  */
2760 MonoString*
2761 mono_string_new_wrapper (const char *text)
2762 {
2763         MonoDomain *domain = mono_domain_get ();
2764
2765         MONO_ARCH_SAVE_REGS;
2766
2767         if (text)
2768                 return mono_string_new (domain, text);
2769
2770         return NULL;
2771 }
2772
2773 /**
2774  * mono_value_box:
2775  * @class: the class of the value
2776  * @value: a pointer to the unboxed data
2777  *
2778  * Returns: A newly created object which contains @value.
2779  */
2780 MonoObject *
2781 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2782 {
2783         MonoObject *res;
2784         int size;
2785         MonoVTable *vtable;
2786
2787         g_assert (class->valuetype);
2788
2789         vtable = mono_class_vtable (domain, class);
2790         size = mono_class_instance_size (class);
2791         res = mono_object_allocate (size, vtable);
2792         mono_profiler_allocation (res, class);
2793
2794         size = size - sizeof (MonoObject);
2795
2796 #if NO_UNALIGNED_ACCESS
2797         memcpy ((char *)res + sizeof (MonoObject), value, size);
2798 #else
2799         switch (size) {
2800         case 1:
2801                 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2802                 break;
2803         case 2:
2804                 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2805                 break;
2806         case 4:
2807                 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2808                 break;
2809         case 8:
2810                 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2811                 break;
2812         default:
2813                 memcpy ((char *)res + sizeof (MonoObject), value, size);
2814         }
2815 #endif
2816         if (class->has_finalize)
2817                 mono_object_register_finalizer (res);
2818         return res;
2819 }
2820
2821 /**
2822  * mono_object_get_domain:
2823  * @obj: object to query
2824  * 
2825  * Returns: the MonoDomain where the object is hosted
2826  */
2827 MonoDomain*
2828 mono_object_get_domain (MonoObject *obj)
2829 {
2830         return mono_object_domain (obj);
2831 }
2832
2833 /**
2834  * mono_object_get_class:
2835  * @obj: object to query
2836  * 
2837  * Returns: the MonOClass of the object.
2838  */
2839 MonoClass*
2840 mono_object_get_class (MonoObject *obj)
2841 {
2842         return mono_object_class (obj);
2843 }
2844 /**
2845  * mono_object_get_size:
2846  * @o: object to query
2847  * 
2848  * Returns: the size, in bytes, of @o
2849  */
2850 guint
2851 mono_object_get_size (MonoObject* o)
2852 {
2853         MonoClass* klass = mono_object_class (o);
2854         
2855         if (klass == mono_defaults.string_class)
2856                 return sizeof (MonoString) + 2 * mono_string_length ((MonoString*) o) + 2;
2857         else if (klass->parent == mono_defaults.array_class)
2858                 return sizeof (MonoArray) + mono_array_element_size (klass) * mono_array_length ((MonoArray*) o);
2859         else
2860                 return mono_class_instance_size (klass);
2861 }
2862
2863 /**
2864  * mono_object_unbox:
2865  * @obj: object to unbox
2866  * 
2867  * Returns: a pointer to the start of the valuetype boxed in this
2868  * object.
2869  *
2870  * This method will assert if the object passed is not a valuetype.
2871  */
2872 gpointer
2873 mono_object_unbox (MonoObject *obj)
2874 {
2875         /* add assert for valuetypes? */
2876         g_assert (obj->vtable->klass->valuetype);
2877         return ((char*)obj) + sizeof (MonoObject);
2878 }
2879
2880 /**
2881  * mono_object_isinst:
2882  * @obj: an object
2883  * @klass: a pointer to a class 
2884  *
2885  * Returns: @obj if @obj is derived from @klass
2886  */
2887 MonoObject *
2888 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2889 {
2890         if (!klass->inited)
2891                 mono_class_init (klass);
2892
2893         if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE) 
2894                 return mono_object_isinst_mbyref (obj, klass);
2895
2896         if (!obj)
2897                 return NULL;
2898
2899         return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2900 }
2901
2902 MonoObject *
2903 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2904 {
2905         MonoVTable *vt;
2906
2907         if (!obj)
2908                 return NULL;
2909
2910         vt = obj->vtable;
2911         
2912         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2913                 if ((klass->interface_id <= vt->max_interface_id) &&
2914                     (vt->interface_offsets [klass->interface_id] != 0))
2915                         return obj;
2916         }
2917         else {
2918                 MonoClass *oklass = vt->klass;
2919                 if ((oklass == mono_defaults.transparent_proxy_class))
2920                         oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2921         
2922                 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2923                         return obj;
2924         }
2925
2926         if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info) 
2927         {
2928                 MonoDomain *domain = mono_domain_get ();
2929                 MonoObject *res;
2930                 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2931                 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2932                 MonoMethod *im = NULL;
2933                 gpointer pa [2];
2934
2935                 im = mono_class_get_method_from_name (rpklass, "CanCastTo", -1);
2936                 im = mono_object_get_virtual_method (rp, im);
2937                 g_assert (im);
2938         
2939                 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2940                 pa [1] = obj;
2941
2942                 res = mono_runtime_invoke (im, rp, pa, NULL);
2943         
2944                 if (*(MonoBoolean *) mono_object_unbox(res)) {
2945                         /* Update the vtable of the remote type, so it can safely cast to this new type */
2946                         mono_upgrade_remote_class (domain, obj, klass);
2947                         return obj;
2948                 }
2949         }
2950
2951         return NULL;
2952 }
2953
2954 /**
2955  * mono_object_castclass_mbyref:
2956  * @obj: an object
2957  * @klass: a pointer to a class 
2958  *
2959  * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2960  */
2961 MonoObject *
2962 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2963 {
2964         if (!obj) return NULL;
2965         if (mono_object_isinst_mbyref (obj, klass)) return obj;
2966                 
2967         mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2968                                                         "System",
2969                                                         "InvalidCastException"));
2970         return NULL;
2971 }
2972
2973 typedef struct {
2974         MonoDomain *orig_domain;
2975         MonoString *ins;
2976         MonoString *res;
2977 } LDStrInfo;
2978
2979 static void
2980 str_lookup (MonoDomain *domain, gpointer user_data)
2981 {
2982         LDStrInfo *info = user_data;
2983         if (info->res || domain == info->orig_domain)
2984                 return;
2985         mono_domain_lock (domain);
2986         info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2987         mono_domain_unlock (domain);
2988 }
2989
2990 static MonoString*
2991 mono_string_is_interned_lookup (MonoString *str, int insert)
2992 {
2993         MonoGHashTable *ldstr_table;
2994         MonoString *res;
2995         MonoDomain *domain;
2996         
2997         domain = ((MonoObject *)str)->vtable->domain;
2998         ldstr_table = domain->ldstr_table;
2999         mono_domain_lock (domain);
3000         if ((res = mono_g_hash_table_lookup (ldstr_table, str))) {
3001                 mono_domain_unlock (domain);
3002                 return res;
3003         }
3004         if (insert) {
3005                 mono_g_hash_table_insert (ldstr_table, str, str);
3006                 mono_domain_unlock (domain);
3007                 return str;
3008         } else {
3009                 LDStrInfo ldstr_info;
3010                 ldstr_info.orig_domain = domain;
3011                 ldstr_info.ins = str;
3012                 ldstr_info.res = NULL;
3013
3014                 mono_domain_foreach (str_lookup, &ldstr_info);
3015                 if (ldstr_info.res) {
3016                         /* 
3017                          * the string was already interned in some other domain:
3018                          * intern it in the current one as well.
3019                          */
3020                         mono_g_hash_table_insert (ldstr_table, str, str);
3021                         mono_domain_unlock (domain);
3022                         return str;
3023                 }
3024         }
3025         mono_domain_unlock (domain);
3026         return NULL;
3027 }
3028
3029 /**
3030  * mono_string_is_interned:
3031  * @o: String to probe
3032  *
3033  * Returns whether the string has been interned.
3034  */
3035 MonoString*
3036 mono_string_is_interned (MonoString *o)
3037 {
3038         return mono_string_is_interned_lookup (o, FALSE);
3039 }
3040
3041 /**
3042  * mono_string_interne:
3043  * @o: String to intern
3044  *
3045  * Interns the string passed.  
3046  * Returns: The interned string.
3047  */
3048 MonoString*
3049 mono_string_intern (MonoString *str)
3050 {
3051         return mono_string_is_interned_lookup (str, TRUE);
3052 }
3053
3054 /**
3055  * mono_ldstr:
3056  * @domain: the domain where the string will be used.
3057  * @image: a metadata context
3058  * @idx: index into the user string table.
3059  * 
3060  * Implementation for the ldstr opcode.
3061  * Returns: a loaded string from the @image/@idx combination.
3062  */
3063 MonoString*
3064 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
3065 {
3066         MONO_ARCH_SAVE_REGS;
3067
3068         if (image->dynamic)
3069                 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
3070         else
3071                 return mono_ldstr_metdata_sig (domain, mono_metadata_user_string (image, idx));
3072 }
3073
3074 /**
3075  * mono_ldstr_metdata_sig
3076  * @domain: the domain for the string
3077  * @sig: the signature of a metadata string
3078  *
3079  * Returns: a MonoString for a string stored in the metadata
3080  */
3081 static MonoString*
3082 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig)
3083 {
3084         const char *str = sig;
3085         MonoString *o, *interned;
3086         size_t len2;
3087         
3088         len2 = mono_metadata_decode_blob_size (str, &str);
3089         len2 >>= 1;
3090
3091         o = mono_string_new_utf16 (domain, (guint16*)str, len2);
3092 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3093         {
3094                 int i;
3095                 guint16 *p2 = (guint16*)mono_string_chars (o);
3096                 for (i = 0; i < len2; ++i) {
3097                         *p2 = GUINT16_FROM_LE (*p2);
3098                         ++p2;
3099                 }
3100         }
3101 #endif
3102         mono_domain_lock (domain);
3103         if ((interned = mono_g_hash_table_lookup (domain->ldstr_table, o))) {
3104                 mono_domain_unlock (domain);
3105                 /* o will get garbage collected */
3106                 return interned;
3107         }
3108
3109         mono_g_hash_table_insert (domain->ldstr_table, o, o);
3110         mono_domain_unlock (domain);
3111
3112         return o;
3113 }
3114
3115 /**
3116  * mono_string_to_utf8:
3117  * @s: a System.String
3118  *
3119  * Return the UTF8 representation for @s.
3120  * the resulting buffer nedds to be freed with g_free().
3121  */
3122 char *
3123 mono_string_to_utf8 (MonoString *s)
3124 {
3125         char *as;
3126         GError *error = NULL;
3127
3128         if (s == NULL)
3129                 return NULL;
3130
3131         if (!s->length)
3132                 return g_strdup ("");
3133
3134         as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
3135         if (error) {
3136                 g_warning (error->message);
3137                 g_error_free (error);
3138         }
3139
3140         return as;
3141 }
3142
3143 /**
3144  * mono_string_to_utf16:
3145  * @s: a MonoString
3146  *
3147  * Return an null-terminated array of the utf-16 chars
3148  * contained in @s. The result must be freed with g_free().
3149  * This is a temporary helper until our string implementation
3150  * is reworked to always include the null terminating char.
3151  */
3152 gunichar2 *
3153 mono_string_to_utf16 (MonoString *s)
3154 {
3155         char *as;
3156
3157         if (s == NULL)
3158                 return NULL;
3159
3160         as = g_malloc ((s->length * 2) + 2);
3161         as [(s->length * 2)] = '\0';
3162         as [(s->length * 2) + 1] = '\0';
3163
3164         if (!s->length) {
3165                 return (gunichar2 *)(as);
3166         }
3167         
3168         memcpy (as, mono_string_chars(s), s->length * 2);
3169         return (gunichar2 *)(as);
3170 }
3171
3172 /**
3173  * mono_string_from_utf16:
3174  * @data: the UTF16 string (LPWSTR) to convert
3175  *
3176  * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString.
3177  *
3178  * Returns: a MonoString.
3179  */
3180 MonoString *
3181 mono_string_from_utf16 (gunichar2 *data)
3182 {
3183         MonoDomain *domain = mono_domain_get ();
3184         int len = 0;
3185
3186         if (!data)
3187                 return NULL;
3188
3189         while (data [len]) len++;
3190
3191         return mono_string_new_utf16 (domain, data, len);
3192 }
3193
3194 static void
3195 default_ex_handler (MonoException *ex)
3196 {
3197         MonoObject *o = (MonoObject*)ex;
3198         g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
3199         exit (1);
3200 }
3201
3202 static MonoExceptionFunc ex_handler = default_ex_handler;
3203
3204 /**
3205  * mono_install_handler:
3206  * @func: exception handler
3207  *
3208  * This is an internal JIT routine used to install the handler for exceptions
3209  * being throwh.
3210  */
3211 void
3212 mono_install_handler (MonoExceptionFunc func)
3213 {
3214         ex_handler = func? func: default_ex_handler;
3215 }
3216
3217 /**
3218  * mono_raise_exception:
3219  * @ex: exception object
3220  *
3221  * Signal the runtime that the exception @ex has been raised in unmanaged code.
3222  */
3223 void
3224 mono_raise_exception (MonoException *ex) 
3225 {
3226         /*
3227          * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
3228          * that will cause gcc to omit the function epilog, causing problems when
3229          * the JIT tries to walk the stack, since the return address on the stack
3230          * will point into the next function in the executable, not this one.
3231          */
3232
3233         if (((MonoObject*)ex)->vtable->klass == mono_defaults.threadabortexception_class)
3234                 mono_thread_current ()->abort_exc = ex;
3235         
3236         ex_handler (ex);
3237 }
3238
3239 /**
3240  * mono_wait_handle_new:
3241  * @domain: Domain where the object will be created
3242  * @handle: Handle for the wait handle
3243  *
3244  * Returns: A new MonoWaitHandle created in the given domain for the given handle
3245  */
3246 MonoWaitHandle *
3247 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
3248 {
3249         MonoWaitHandle *res;
3250
3251         res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
3252
3253         res->handle = handle;
3254
3255         return res;
3256 }
3257
3258 /**
3259  * mono_async_result_new:
3260  * @domain:domain where the object will be created.
3261  * @handle: wait handle.
3262  * @state: state to pass to AsyncResult
3263  * @data: C closure data.
3264  *
3265  * Creates a new MonoAsyncResult (AsyncResult C# class) in the given domain.
3266  * If the handle is not null, the handle is initialized to a MonOWaitHandle.
3267  *
3268  */
3269 MonoAsyncResult *
3270 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
3271 {
3272         MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
3273         MonoMethod *method = mono_get_context_capture_method ();
3274
3275         /* we must capture the execution context from the original thread */
3276         if (method) {
3277                 res->execution_context = mono_runtime_invoke (method, NULL, NULL, NULL);
3278                 /* note: result may be null if the flow is suppressed */
3279         }
3280
3281         res->data = data;
3282         res->async_state = state;
3283         if (handle != NULL)
3284                 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
3285
3286         res->sync_completed = FALSE;
3287         res->completed = FALSE;
3288
3289         return res;
3290 }
3291
3292 void
3293 mono_message_init (MonoDomain *domain,
3294                    MonoMethodMessage *this, 
3295                    MonoReflectionMethod *method,
3296                    MonoArray *out_args)
3297 {
3298         MonoMethodSignature *sig = mono_method_signature (method->method);
3299         MonoString *name;
3300         int i, j;
3301         char **names;
3302         guint8 arg_type;
3303
3304         this->method = method;
3305
3306         this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
3307         this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
3308         this->async_result = NULL;
3309         this->call_type = CallType_Sync;
3310
3311         names = g_new (char *, sig->param_count);
3312         mono_method_get_param_names (method->method, (const char **) names);
3313         this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
3314         
3315         for (i = 0; i < sig->param_count; i++) {
3316                  name = mono_string_new (domain, names [i]);
3317                  mono_array_set (this->names, gpointer, i, name);       
3318         }
3319
3320         g_free (names);
3321         for (i = 0, j = 0; i < sig->param_count; i++) {
3322
3323                 if (sig->params [i]->byref) {
3324                         if (out_args) {
3325                                 gpointer arg = mono_array_get (out_args, gpointer, j);
3326                                 mono_array_set (this->args, gpointer, i, arg);
3327                                 j++;
3328                         }
3329                         arg_type = 2;
3330                         if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
3331                                 arg_type |= 1;
3332                 } else {
3333                         arg_type = 1;
3334                         if (sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT)
3335                                 arg_type |= 4;
3336                 }
3337                 mono_array_set (this->arg_types, guint8, i, arg_type);
3338         }
3339 }
3340
3341 /**
3342  * mono_remoting_invoke:
3343  * @real_proxy: pointer to a RealProxy object
3344  * @msg: The MonoMethodMessage to execute
3345  * @exc: used to store exceptions
3346  * @out_args: used to store output arguments
3347  *
3348  * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
3349  * IMessage interface and it is not trivial to extract results from there. So
3350  * we call an helper method PrivateInvoke instead of calling
3351  * RealProxy::Invoke() directly.
3352  *
3353  * Returns: the result object.
3354  */
3355 MonoObject *
3356 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, 
3357                       MonoObject **exc, MonoArray **out_args)
3358 {
3359         MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
3360         gpointer pa [4];
3361
3362         /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
3363
3364         if (!im) {
3365                 im = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "PrivateInvoke", 4);
3366                 g_assert (im);
3367                 real_proxy->vtable->domain->private_invoke_method = im;
3368         }
3369
3370         pa [0] = real_proxy;
3371         pa [1] = msg;
3372         pa [2] = exc;
3373         pa [3] = out_args;
3374
3375         return mono_runtime_invoke (im, NULL, pa, exc);
3376 }
3377
3378 MonoObject *
3379 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, 
3380                      MonoObject **exc, MonoArray **out_args) 
3381 {
3382         MonoDomain *domain; 
3383         MonoMethod *method;
3384         MonoMethodSignature *sig;
3385         MonoObject *ret;
3386         int i, j, outarg_count = 0;
3387
3388         if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
3389
3390                 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
3391                 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3392                         target = tp->rp->unwrapped_server;
3393                 } else {
3394                         return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
3395                 }
3396         }
3397
3398         domain = mono_domain_get (); 
3399         method = msg->method->method;
3400         sig = mono_method_signature (method);
3401
3402         for (i = 0; i < sig->param_count; i++) {
3403                 if (sig->params [i]->byref) 
3404                         outarg_count++;
3405         }
3406
3407         *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3408         *exc = NULL;
3409
3410         ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
3411
3412         for (i = 0, j = 0; i < sig->param_count; i++) {
3413                 if (sig->params [i]->byref) {
3414                         gpointer arg;
3415                         arg = mono_array_get (msg->args, gpointer, i);
3416                         mono_array_set (*out_args, gpointer, j, arg);
3417                         j++;
3418                 }
3419         }
3420
3421         return ret;
3422 }
3423
3424 /**
3425  * mono_print_unhandled_exception:
3426  * @exc: The exception
3427  *
3428  * Prints the unhandled exception.
3429  */
3430 void
3431 mono_print_unhandled_exception (MonoObject *exc)
3432 {
3433         char *message = (char *) "";
3434         MonoString *str; 
3435         MonoMethod *method;
3436         MonoClass *klass;
3437         gboolean free_message = FALSE;
3438
3439         if (mono_object_isinst (exc, mono_defaults.exception_class)) {
3440                 klass = exc->vtable->klass;
3441                 method = NULL;
3442                 while (klass && method == NULL) {
3443                         method = mono_class_get_method_from_name_flags (klass, "ToString", 0, METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_PUBLIC);
3444                         if (method == NULL)
3445                                 klass = klass->parent;
3446                 }
3447
3448                 g_assert (method);
3449
3450                 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
3451                 if (str) {
3452                         message = mono_string_to_utf8 (str);
3453                         free_message = TRUE;
3454                 }
3455         }                               
3456
3457         /*
3458          * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space, 
3459          *         exc->vtable->klass->name, message);
3460          */
3461         g_printerr ("\nUnhandled Exception: %s\n", message);
3462         
3463         if (free_message)
3464                 g_free (message);
3465 }
3466
3467 /**
3468  * mono_delegate_ctor:
3469  * @this: pointer to an uninitialized delegate object
3470  * @target: target object
3471  * @addr: pointer to native code
3472  *
3473  * This is used to initialize a delegate. We also insert the method_info if
3474  * we find the info with mono_jit_info_table_find().
3475  */
3476 void
3477 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
3478 {
3479         MonoDomain *domain = mono_domain_get ();
3480         MonoDelegate *delegate = (MonoDelegate *)this;
3481         MonoMethod *method = NULL;
3482         MonoClass *class;
3483         MonoJitInfo *ji;
3484
3485         g_assert (this);
3486         g_assert (addr);
3487
3488         class = this->vtable->klass;
3489
3490         if ((ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (addr)))) {
3491                 method = ji->method;
3492                 delegate->method_info = mono_method_get_object (domain, method, NULL);
3493         }
3494
3495         if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
3496                 g_assert (method);
3497                 method = mono_marshal_get_remoting_invoke (method);
3498                 delegate->method_ptr = mono_compile_method (method);
3499                 delegate->target = target;
3500         } else if (mono_method_signature (method)->hasthis && method->klass->valuetype) {
3501                 method = mono_marshal_get_unbox_wrapper (method);
3502                 delegate->method_ptr = mono_compile_method (method);
3503                 delegate->target = target;
3504         } else {
3505                 if (method) {
3506                         /* 
3507                          * Replace the original trampoline with a delegate trampoline
3508                          * which will patch delegate->method_ptr with the address of the
3509                          * compiled method.
3510                          */
3511                         addr = arch_create_delegate_trampoline (method, addr);
3512                 }
3513                 delegate->method_ptr = addr;
3514                 delegate->target = target;
3515         }
3516 }
3517
3518 /**
3519  * mono_method_call_message_new:
3520  * @method: method to encapsulate
3521  * @params: parameters to the method
3522  * @invoke: optional, delegate invoke.
3523  * @cb: async callback delegate.
3524  * @state: state passed to the async callback.
3525  *
3526  * Translates arguments pointers into a MonoMethodMessage.
3527  */
3528 MonoMethodMessage *
3529 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke, 
3530                               MonoDelegate **cb, MonoObject **state)
3531 {
3532         MonoDomain *domain = mono_domain_get ();
3533         MonoMethodSignature *sig = mono_method_signature (method);
3534         MonoMethodMessage *msg;
3535         int i, count, type;
3536
3537         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class); 
3538         
3539         if (invoke) {
3540                 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
3541                 count =  sig->param_count - 2;
3542         } else {
3543                 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
3544                 count =  sig->param_count;
3545         }
3546
3547         for (i = 0; i < count; i++) {
3548                 gpointer vpos;
3549                 MonoClass *class;
3550                 MonoObject *arg;
3551
3552                 if (sig->params [i]->byref)
3553                         vpos = *((gpointer *)params [i]);
3554                 else 
3555                         vpos = params [i];
3556
3557                 type = sig->params [i]->type;
3558                 class = mono_class_from_mono_type (sig->params [i]);
3559
3560                 if (class->valuetype)
3561                         arg = mono_value_box (domain, class, vpos);
3562                 else 
3563                         arg = *((MonoObject **)vpos);
3564                       
3565                 mono_array_set (msg->args, gpointer, i, arg);
3566         }
3567
3568         if (cb != NULL && state != NULL) {
3569                 *cb = *((MonoDelegate **)params [i]);
3570                 i++;
3571                 *state = *((MonoObject **)params [i]);
3572         }
3573
3574         return msg;
3575 }
3576
3577 /**
3578  * mono_method_return_message_restore:
3579  *
3580  * Restore results from message based processing back to arguments pointers
3581  */
3582 void
3583 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
3584 {
3585         MonoMethodSignature *sig = mono_method_signature (method);
3586         int i, j, type, size, out_len;
3587         
3588         if (out_args == NULL)
3589                 return;
3590         out_len = mono_array_length (out_args);
3591         if (out_len == 0)
3592                 return;
3593
3594         for (i = 0, j = 0; i < sig->param_count; i++) {
3595                 MonoType *pt = sig->params [i];
3596
3597                 if (pt->byref) {
3598                         char *arg;
3599                         if (j >= out_len)
3600                                 mono_raise_exception (mono_get_exception_execution_engine ("The proxy call returned an incorrect number of output arguments"));
3601
3602                         arg = mono_array_get (out_args, gpointer, j);
3603                         type = pt->type;
3604
3605                         switch (type) {
3606                         case MONO_TYPE_VOID:
3607                                 g_assert_not_reached ();
3608                                 break;
3609                         case MONO_TYPE_U1:
3610                         case MONO_TYPE_I1:
3611                         case MONO_TYPE_BOOLEAN:
3612                         case MONO_TYPE_U2:
3613                         case MONO_TYPE_I2:
3614                         case MONO_TYPE_CHAR:
3615                         case MONO_TYPE_U4:
3616                         case MONO_TYPE_I4:
3617                         case MONO_TYPE_I8:
3618                         case MONO_TYPE_U8:
3619                         case MONO_TYPE_R4:
3620                         case MONO_TYPE_R8:
3621                         case MONO_TYPE_VALUETYPE: {
3622                                 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
3623                                 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size); 
3624                                 break;
3625                         }
3626                         case MONO_TYPE_STRING:
3627                         case MONO_TYPE_CLASS: 
3628                         case MONO_TYPE_ARRAY:
3629                         case MONO_TYPE_SZARRAY:
3630                         case MONO_TYPE_OBJECT:
3631                                 **((MonoObject ***)params [i]) = (MonoObject *)arg;
3632                                 break;
3633                         default:
3634                                 g_assert_not_reached ();
3635                         }
3636
3637                         j++;
3638                 }
3639         }
3640 }
3641
3642 /**
3643  * mono_load_remote_field:
3644  * @this: pointer to an object
3645  * @klass: klass of the object containing @field
3646  * @field: the field to load
3647  * @res: a storage to store the result
3648  *
3649  * This method is called by the runtime on attempts to load fields of
3650  * transparent proxy objects. @this points to such TP, @klass is the class of
3651  * the object containing @field. @res is a storage location which can be
3652  * used to store the result.
3653  *
3654  * Returns: an address pointing to the value of field.
3655  */
3656 gpointer
3657 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
3658 {
3659         static MonoMethod *getter = NULL;
3660         MonoDomain *domain = mono_domain_get ();
3661         MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3662         MonoClass *field_class;
3663         MonoMethodMessage *msg;
3664         MonoArray *out_args;
3665         MonoObject *exc;
3666         gpointer tmp;
3667
3668         g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3669
3670         if (!res)
3671                 res = &tmp;
3672
3673         if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3674                 mono_field_get_value (tp->rp->unwrapped_server, field, res);
3675                 return res;
3676         }
3677         
3678         if (!getter) {
3679                 getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
3680                 g_assert (getter);
3681         }
3682         
3683         field_class = mono_class_from_mono_type (field->type);
3684
3685         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3686         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3687         mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3688
3689         mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3690         mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3691
3692         mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3693
3694         if (exc) mono_raise_exception ((MonoException *)exc);
3695
3696         if (mono_array_length (out_args) == 0)
3697                 return NULL;
3698
3699         *res = mono_array_get (out_args, MonoObject *, 0);
3700
3701         if (field_class->valuetype) {
3702                 return ((char *)*res) + sizeof (MonoObject);
3703         } else
3704                 return res;
3705 }
3706
3707 /**
3708  * mono_load_remote_field_new:
3709  * @this: 
3710  * @klass: 
3711  * @field:
3712  *
3713  * Missing documentation.
3714  */
3715 MonoObject *
3716 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
3717 {
3718         static MonoMethod *getter = NULL;
3719         MonoDomain *domain = mono_domain_get ();
3720         MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3721         MonoClass *field_class;
3722         MonoMethodMessage *msg;
3723         MonoArray *out_args;
3724         MonoObject *exc, *res;
3725
3726         g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3727
3728         field_class = mono_class_from_mono_type (field->type);
3729
3730         if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3731                 gpointer val;
3732                 if (field_class->valuetype) {
3733                         res = mono_object_new (domain, field_class);
3734                         val = ((gchar *) res) + sizeof (MonoObject);
3735                 } else {
3736                         val = &res;
3737                 }
3738                 mono_field_get_value (tp->rp->unwrapped_server, field, val);
3739                 return res;
3740         }
3741
3742         if (!getter) {
3743                 getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
3744                 g_assert (getter);
3745         }
3746         
3747         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3748         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3749
3750         mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3751
3752         mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3753         mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3754
3755         mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3756
3757         if (exc) mono_raise_exception ((MonoException *)exc);
3758
3759         if (mono_array_length (out_args) == 0)
3760                 res = NULL;
3761         else
3762                 res = mono_array_get (out_args, MonoObject *, 0);
3763
3764         return res;
3765 }
3766
3767 /**
3768  * mono_store_remote_field:
3769  * @this: pointer to an object
3770  * @klass: klass of the object containing @field
3771  * @field: the field to load
3772  * @val: the value/object to store
3773  *
3774  * This method is called by the runtime on attempts to store fields of
3775  * transparent proxy objects. @this points to such TP, @klass is the class of
3776  * the object containing @field. @val is the new value to store in @field.
3777  */
3778 void
3779 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3780 {
3781         static MonoMethod *setter = NULL;
3782         MonoDomain *domain = mono_domain_get ();
3783         MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3784         MonoClass *field_class;
3785         MonoMethodMessage *msg;
3786         MonoArray *out_args;
3787         MonoObject *exc;
3788         MonoObject *arg;
3789
3790         g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3791
3792         field_class = mono_class_from_mono_type (field->type);
3793
3794         if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3795                 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3796                 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3797                 return;
3798         }
3799
3800         if (!setter) {
3801                 setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
3802                 g_assert (setter);
3803         }
3804
3805         if (field_class->valuetype)
3806                 arg = mono_value_box (domain, field_class, val);
3807         else 
3808                 arg = *((MonoObject **)val);
3809                 
3810
3811         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3812         mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3813
3814         mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3815         mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3816         mono_array_set (msg->args, gpointer, 2, arg);
3817
3818         mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3819
3820         if (exc) mono_raise_exception ((MonoException *)exc);
3821 }
3822
3823 /**
3824  * mono_store_remote_field_new:
3825  * @this:
3826  * @klass:
3827  * @field:
3828  * @arg:
3829  *
3830  * Missing documentation
3831  */
3832 void
3833 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3834 {
3835         static MonoMethod *setter = NULL;
3836         MonoDomain *domain = mono_domain_get ();
3837         MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3838         MonoClass *field_class;
3839         MonoMethodMessage *msg;
3840         MonoArray *out_args;
3841         MonoObject *exc;
3842
3843         g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3844
3845         field_class = mono_class_from_mono_type (field->type);
3846
3847         if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3848                 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3849                 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3850                 return;
3851         }
3852
3853         if (!setter) {
3854                 setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
3855                 g_assert (setter);
3856         }
3857
3858         msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3859         mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3860
3861         mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3862         mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3863         mono_array_set (msg->args, gpointer, 2, arg);
3864
3865         mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3866
3867         if (exc) mono_raise_exception ((MonoException *)exc);
3868 }
3869
3870 /*
3871  * mono_get_addr_from_ftnptr:
3872  *
3873  *   Given a pointer to a function descriptor, return the function address.
3874  * This is only needed on IA64.
3875  */
3876 gpointer
3877 mono_get_addr_from_ftnptr (gpointer descr)
3878 {
3879 #ifdef __ia64__
3880         return *(gpointer*)descr;
3881 #else
3882         return descr;
3883 #endif
3884 }