2008-06-13 Mark Probst <mark.probst@gmail.com>
[mono.git] / mono / metadata / domain.c
1 /*
2  * domain.c: MonoDomain functions
3  *
4  * Author:
5  *      Dietmar Maurer (dietmar@ximian.com)
6  *      Patrik Torstensson
7  *
8  * (C) 2001 Ximian, Inc.
9  */
10
11 #include <config.h>
12 #include <glib.h>
13 #include <string.h>
14 #include <sys/stat.h>
15
16 #include <mono/metadata/gc-internal.h>
17
18 #include <mono/utils/mono-compiler.h>
19 #include <mono/utils/mono-logger.h>
20 #include <mono/utils/mono-membar.h>
21 #include <mono/utils/mono-counters.h>
22 #include <mono/metadata/object.h>
23 #include <mono/metadata/object-internals.h>
24 #include <mono/metadata/domain-internals.h>
25 #include <mono/metadata/class-internals.h>
26 #include <mono/metadata/assembly.h>
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/rawbuffer.h>
29 #include <mono/metadata/metadata-internals.h>
30 #include <mono/metadata/gc-internal.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-debug-debugger.h>
33 #include <mono/metadata/mono-config.h>
34 #include <mono/metadata/threads-types.h>
35 #include <metadata/threads.h>
36 #include <metadata/profiler-private.h>
37 #include <mono/metadata/coree.h>
38
39 /* #define DEBUG_DOMAIN_UNLOAD */
40
41 /* we need to use both the Tls* functions and __thread because
42  * some archs may generate faster jit code with one meachanism
43  * or the other (we used to do it because tls slots were GC-tracked,
44  * but we can't depend on this).
45  */
46 static guint32 appdomain_thread_id = -1;
47  
48 #ifdef HAVE_KW_THREAD
49 static __thread MonoDomain * tls_appdomain MONO_TLS_FAST;
50 #define GET_APPDOMAIN() tls_appdomain
51 #define SET_APPDOMAIN(x) do { \
52         tls_appdomain = x; \
53         TlsSetValue (appdomain_thread_id, x); \
54 } while (FALSE)
55
56 #else
57
58 #define GET_APPDOMAIN() ((MonoDomain *)TlsGetValue (appdomain_thread_id))
59 #define SET_APPDOMAIN(x) TlsSetValue (appdomain_thread_id, x);
60
61 #endif
62
63 #define GET_APPCONTEXT() (mono_thread_current ()->current_appcontext)
64 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_current (), current_appcontext, (x))
65
66 static guint16 appdomain_list_size = 0;
67 static guint16 appdomain_next = 0;
68 static MonoDomain **appdomains_list = NULL;
69 static MonoImage *exe_image;
70
71 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
72 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
73 static CRITICAL_SECTION appdomains_mutex;
74
75 static MonoDomain *mono_root_domain = NULL;
76
77 /* some statistics */
78 static int max_domain_code_size = 0;
79 static int max_domain_code_alloc = 0;
80 static int total_domain_code_alloc = 0;
81
82 /* AppConfigInfo: Information about runtime versions supported by an 
83  * aplication.
84  */
85 typedef struct {
86         GSList *supported_runtimes;
87         char *required_runtime;
88         int configuration_count;
89         int startup_count;
90 } AppConfigInfo;
91
92 /*
93  * AotModuleInfo: Contains information about AOT modules.
94  */
95 typedef struct {
96         MonoImage *image;
97         gpointer start, end;
98 } AotModuleInfo;
99
100 static const MonoRuntimeInfo *current_runtime = NULL;
101
102 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
103
104 /*
105  * Contains information about AOT loaded code.
106  */
107 static MonoAotModuleInfoTable *aot_modules = NULL;
108
109 /* This is the list of runtime versions supported by this JIT.
110  */
111 static const MonoRuntimeInfo supported_runtimes[] = {
112         {"v1.0.3705", "1.0", { {1,0,5000,0}, {7,0,5000,0} }     },
113         {"v1.1.4322", "1.0", { {1,0,5000,0}, {7,0,5000,0} }     },
114         {"v2.0.50215","2.0", { {2,0,0,0},    {8,0,0,0} }        },
115         {"v2.0.50727","2.0", { {2,0,0,0},    {8,0,0,0} }        },
116         {"moonlight", "2.1", { {2,0,5,0},    {9,0,0,0} }    },
117 };
118
119
120 /* The stable runtime version */
121 #define DEFAULT_RUNTIME_VERSION "v1.1.4322"
122
123 /* This is intentionally not in the header file, so people don't misuse it. */
124 extern void _mono_debug_init_corlib (MonoDomain *domain);
125
126 static void
127 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
128
129 static const MonoRuntimeInfo*
130 get_runtime_by_version (const char *version);
131
132 static MonoImage*
133 mono_jit_info_find_aot_module (guint8* addr);
134
135 guint32
136 mono_domain_get_tls_key (void)
137 {
138         return appdomain_thread_id;
139 }
140
141 gint32
142 mono_domain_get_tls_offset (void)
143 {
144         int offset = -1;
145         MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
146 /*      __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:" 
147                 : "=r" (offset));*/
148         return offset;
149 }
150
151 #define JIT_INFO_TABLE_FILL_RATIO_NOM           3
152 #define JIT_INFO_TABLE_FILL_RATIO_DENOM         4
153 #define JIT_INFO_TABLE_FILLED_NUM_ELEMENTS      (MONO_JIT_INFO_TABLE_CHUNK_SIZE * JIT_INFO_TABLE_FILL_RATIO_NOM / JIT_INFO_TABLE_FILL_RATIO_DENOM)
154
155 #define JIT_INFO_TABLE_LOW_WATERMARK(n)         ((n) / 2)
156 #define JIT_INFO_TABLE_HIGH_WATERMARK(n)        ((n) * 5 / 6)
157
158 #define JIT_INFO_TOMBSTONE_MARKER       ((MonoMethod*)NULL)
159 #define IS_JIT_INFO_TOMBSTONE(ji)       ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
160
161 #define JIT_INFO_TABLE_HAZARD_INDEX             0
162 #define JIT_INFO_HAZARD_INDEX                   1
163
164 static int
165 jit_info_table_num_elements (MonoJitInfoTable *table)
166 {
167         int i;
168         int num_elements = 0;
169
170         for (i = 0; i < table->num_chunks; ++i) {
171                 MonoJitInfoTableChunk *chunk = table->chunks [i];
172                 int chunk_num_elements = chunk->num_elements;
173                 int j;
174
175                 for (j = 0; j < chunk_num_elements; ++j) {
176                         if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
177                                 ++num_elements;
178                 }
179         }
180
181         return num_elements;
182 }
183
184 static MonoJitInfoTableChunk*
185 jit_info_table_new_chunk (void)
186 {
187         MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
188         chunk->refcount = 1;
189
190         return chunk;
191 }
192
193 static MonoJitInfoTable *
194 jit_info_table_new (MonoDomain *domain)
195 {
196         MonoJitInfoTable *table = g_malloc0 (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*));
197
198         table->domain = domain;
199         table->num_chunks = 1;
200         table->chunks [0] = jit_info_table_new_chunk ();
201
202         return table;
203 }
204
205 static void
206 jit_info_table_free (MonoJitInfoTable *table)
207 {
208         int i;
209         int num_chunks = table->num_chunks;
210         MonoDomain *domain = table->domain;
211
212         mono_domain_lock (domain);
213
214         table->domain->num_jit_info_tables--;
215         if (table->domain->num_jit_info_tables <= 1) {
216                 GSList *list;
217
218                 for (list = table->domain->jit_info_free_queue; list; list = list->next)
219                         g_free (list->data);
220
221                 g_slist_free (table->domain->jit_info_free_queue);
222                 table->domain->jit_info_free_queue = NULL;
223         }
224
225         /* At this point we assume that there are no other threads
226            still accessing the table, so we don't have to worry about
227            hazardous pointers. */
228
229         for (i = 0; i < num_chunks; ++i) {
230                 MonoJitInfoTableChunk *chunk = table->chunks [i];
231                 int num_elements;
232                 int j;
233
234                 if (--chunk->refcount > 0)
235                         continue;
236
237                 num_elements = chunk->num_elements;
238                 for (j = 0; j < num_elements; ++j) {
239                         MonoJitInfo *ji = chunk->data [j];
240
241                         if (IS_JIT_INFO_TOMBSTONE (ji))
242                                 g_free (ji);
243                 }
244
245                 g_free (chunk);
246         }
247
248         mono_domain_unlock (domain);
249
250         g_free (table);
251 }
252
253 /* Can be called with hp==NULL, in which case it acts as an ordinary
254    pointer fetch.  It's used that way indirectly from
255    mono_jit_info_table_add(), which doesn't have to care about hazards
256    because it holds the respective domain lock. */
257 static gpointer
258 get_hazardous_pointer (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index)
259 {
260         gpointer p;
261
262         for (;;) {
263                 /* Get the pointer */
264                 p = *pp;
265                 /* If we don't have hazard pointers just return the
266                    pointer. */
267                 if (!hp)
268                         return p;
269                 /* Make it hazardous */
270                 mono_hazard_pointer_set (hp, hazard_index, p);
271                 /* Check that it's still the same.  If not, try
272                    again. */
273                 if (*pp != p) {
274                         mono_hazard_pointer_clear (hp, hazard_index);
275                         continue;
276                 }
277                 break;
278         }
279
280         return p;
281 }
282
283 /* The jit_info_table is sorted in ascending order by the end
284  * addresses of the compiled methods.  The reason why we have to do
285  * this is that once we introduce tombstones, it becomes possible for
286  * code ranges to overlap, and if we sort by code start and insert at
287  * the back of the table, we cannot guarantee that we won't overlook
288  * an entry.
289  *
290  * There are actually two possible ways to do the sorting and
291  * inserting which work with our lock-free mechanism:
292  *
293  * 1. Sort by start address and insert at the front.  When looking for
294  * an entry, find the last one with a start address lower than the one
295  * you're looking for, then work your way to the front of the table.
296  *
297  * 2. Sort by end address and insert at the back.  When looking for an
298  * entry, find the first one with an end address higher than the one
299  * you're looking for, then work your way to the end of the table.
300  *
301  * We chose the latter out of convenience.
302  */
303 static int
304 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
305 {
306         int left = 0, right = table->num_chunks;
307
308         g_assert (left < right);
309
310         do {
311                 int pos = (left + right) / 2;
312                 MonoJitInfoTableChunk *chunk = table->chunks [pos];
313
314                 if (addr < chunk->last_code_end)
315                         right = pos;
316                 else
317                         left = pos + 1;
318         } while (left < right);
319         g_assert (left == right);
320
321         if (left >= table->num_chunks)
322                 return table->num_chunks - 1;
323         return left;
324 }
325
326 static int
327 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
328 {
329         int left = 0, right = chunk->num_elements;
330
331         while (left < right) {
332                 int pos = (left + right) / 2;
333                 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
334                 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
335
336                 if (addr < code_end)
337                         right = pos;
338                 else
339                         left = pos + 1;
340         }
341         g_assert (left == right);
342
343         return left;
344 }
345
346 MonoJitInfo*
347 mono_jit_info_table_find (MonoDomain *domain, char *addr)
348 {
349         MonoJitInfoTable *table;
350         MonoJitInfo *ji;
351         int chunk_pos, pos;
352         MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
353
354         ++mono_stats.jit_info_table_lookup_count;
355
356         /* First we have to get the domain's jit_info_table.  This is
357            complicated by the fact that a writer might substitute a
358            new table and free the old one.  What the writer guarantees
359            us is that it looks at the hazard pointers after it has
360            changed the jit_info_table pointer.  So, if we guard the
361            table by a hazard pointer and make sure that the pointer is
362            still there after we've made it hazardous, we don't have to
363            worry about the writer freeing the table. */
364         table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
365
366         chunk_pos = jit_info_table_index (table, (gint8*)addr);
367         g_assert (chunk_pos < table->num_chunks);
368
369         pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
370
371         /* We now have a position that's very close to that of the
372            first element whose end address is higher than the one
373            we're looking for.  If we don't have the exact position,
374            then we have a position below that one, so we'll just
375            search upward until we find our element. */
376         do {
377                 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
378
379                 while (pos < chunk->num_elements) {
380                         ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
381
382                         ++pos;
383
384                         if (IS_JIT_INFO_TOMBSTONE (ji)) {
385                                 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
386                                 continue;
387                         }
388                         if ((gint8*)addr >= (gint8*)ji->code_start
389                                         && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
390                                 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
391                                 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
392                                 return ji;
393                         }
394
395                         /* If we find a non-tombstone element which is already
396                            beyond what we're looking for, we have to end the
397                            search. */
398                         if ((gint8*)addr < (gint8*)ji->code_start)
399                                 break;
400                 }
401
402                 ++chunk_pos;
403                 pos = 0;
404          } while (chunk_pos < table->num_chunks);
405
406         mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
407         mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
408
409         /* maybe it is shared code, so we also search in the root domain */
410         ji = NULL;
411         if (domain != mono_root_domain)
412                 ji = mono_jit_info_table_find (mono_root_domain, addr);
413
414         if (ji == NULL) {
415                 /* Maybe its an AOT module */
416                 MonoImage *image = mono_jit_info_find_aot_module ((guint8*)addr);
417                 if (image)
418                         ji = jit_info_find_in_aot_func (domain, image, addr);
419         }
420         
421         return ji;
422 }
423
424 static G_GNUC_UNUSED void
425 jit_info_table_check (MonoJitInfoTable *table)
426 {
427         int i;
428
429         for (i = 0; i < table->num_chunks; ++i) {
430                 MonoJitInfoTableChunk *chunk = table->chunks [i];
431                 int j;
432
433                 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
434                 if (chunk->refcount > 10)
435                         printf("warning: chunk refcount is %d\n", chunk->refcount);
436                 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
437
438                 for (j = 0; j < chunk->num_elements; ++j) {
439                         MonoJitInfo *this = chunk->data [j];
440                         MonoJitInfo *next;
441
442                         g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
443
444                         if (j < chunk->num_elements - 1)
445                                 next = chunk->data [j + 1];
446                         else if (i < table->num_chunks - 1) {
447                                 int k;
448
449                                 for (k = i + 1; k < table->num_chunks; ++k)
450                                         if (table->chunks [k]->num_elements > 0)
451                                                 break;
452
453                                 if (k >= table->num_chunks)
454                                         return;
455
456                                 g_assert (table->chunks [k]->num_elements > 0);
457                                 next = table->chunks [k]->data [0];
458                         } else
459                                 return;
460
461                         g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
462                 }
463         }
464 }
465
466 static MonoJitInfoTable*
467 jit_info_table_realloc (MonoJitInfoTable *old)
468 {
469         int i;
470         int num_elements = jit_info_table_num_elements (old);
471         int required_size;
472         int num_chunks;
473         int new_chunk, new_element;
474         MonoJitInfoTable *new;
475
476         /* number of needed places for elements needed */
477         required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
478         num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
479
480         new = g_malloc (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*) * num_chunks);
481         new->domain = old->domain;
482         new->num_chunks = num_chunks;
483
484         for (i = 0; i < num_chunks; ++i)
485                 new->chunks [i] = jit_info_table_new_chunk ();
486
487         new_chunk = 0;
488         new_element = 0;
489         for (i = 0; i < old->num_chunks; ++i) {
490                 MonoJitInfoTableChunk *chunk = old->chunks [i];
491                 int chunk_num_elements = chunk->num_elements;
492                 int j;
493
494                 for (j = 0; j < chunk_num_elements; ++j) {
495                         if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
496                                 g_assert (new_chunk < num_chunks);
497                                 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
498                                 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
499                                         new->chunks [new_chunk]->num_elements = new_element;
500                                         ++new_chunk;
501                                         new_element = 0;
502                                 }
503                         }
504                 }
505         }
506
507         if (new_chunk < num_chunks) {
508                 g_assert (new_chunk == num_chunks - 1);
509                 new->chunks [new_chunk]->num_elements = new_element;
510                 g_assert (new->chunks [new_chunk]->num_elements > 0);
511         }
512
513         for (i = 0; i < num_chunks; ++i) {
514                 MonoJitInfoTableChunk *chunk = new->chunks [i];
515                 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
516
517                 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
518         }
519
520         return new;
521 }
522
523 static void
524 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
525 {
526         MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
527         MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
528
529         g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
530
531         new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
532         new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
533
534         memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
535         memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
536
537         new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
538                 + new1->data [new1->num_elements - 1]->code_size;
539         new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
540                 + new2->data [new2->num_elements - 1]->code_size;
541
542         *new1p = new1;
543         *new2p = new2;
544 }
545
546 static MonoJitInfoTable*
547 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
548 {
549         MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
550                 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
551         int i, j;
552
553         new_table->domain = table->domain;
554         new_table->num_chunks = table->num_chunks + 1;
555
556         j = 0;
557         for (i = 0; i < table->num_chunks; ++i) {
558                 if (table->chunks [i] == chunk) {
559                         jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
560                         j += 2;
561                 } else {
562                         new_table->chunks [j] = table->chunks [i];
563                         ++new_table->chunks [j]->refcount;
564                         ++j;
565                 }
566         }
567
568         g_assert (j == new_table->num_chunks);
569
570         return new_table;
571 }
572
573 static MonoJitInfoTableChunk*
574 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
575 {
576         MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
577         int i, j;
578
579         j = 0;
580         for (i = 0; i < old->num_elements; ++i) {
581                 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
582                         new->data [j++] = old->data [i];
583         }
584
585         new->num_elements = j;
586         if (new->num_elements > 0)
587                 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
588         else
589                 new->last_code_end = old->last_code_end;
590
591         return new;
592 }
593
594 static MonoJitInfoTable*
595 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
596 {
597         MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
598                 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
599         int i, j;
600
601         new_table->domain = table->domain;
602         new_table->num_chunks = table->num_chunks;
603
604         j = 0;
605         for (i = 0; i < table->num_chunks; ++i) {
606                 if (table->chunks [i] == chunk)
607                         new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
608                 else {
609                         new_table->chunks [j] = table->chunks [i];
610                         ++new_table->chunks [j]->refcount;
611                         ++j;
612                 }
613         }
614
615         g_assert (j == new_table->num_chunks);
616
617         return new_table;
618 }
619
620 /* As we add an element to the table the case can arise that the chunk
621  * to which we need to add is already full.  In that case we have to
622  * allocate a new table and do something about that chunk.  We have
623  * several strategies:
624  *
625  * If the number of elements in the table is below the low watermark
626  * or above the high watermark, we reallocate the whole table.
627  * Otherwise we only concern ourselves with the overflowing chunk:
628  *
629  * If there are no tombstones in the chunk then we split the chunk in
630  * two, each half full.
631  *
632  * If the chunk does contain tombstones, we just make a new copy of
633  * the chunk without the tombstones, which will have room for at least
634  * the one element we have to add.
635  */
636 static MonoJitInfoTable*
637 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
638 {
639         int num_elements = jit_info_table_num_elements (table);
640         int i;
641
642         if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
643                         || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
644                 //printf ("reallocing table\n");
645                 return jit_info_table_realloc (table);
646         }
647
648         /* count the number of non-tombstone elements in the chunk */
649         num_elements = 0;
650         for (i = 0; i < chunk->num_elements; ++i) {
651                 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
652                         ++num_elements;
653         }
654
655         if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
656                 //printf ("splitting chunk\n");
657                 return jit_info_table_copy_and_split_chunk (table, chunk);
658         }
659
660         //printf ("purifying chunk\n");
661         return jit_info_table_copy_and_purify_chunk (table, chunk);
662 }
663
664 /* We add elements to the table by first making space for them by
665  * shifting the elements at the back to the right, one at a time.
666  * This results in duplicate entries during the process, but during
667  * all the time the table is in a sorted state.  Also, when an element
668  * is replaced by another one, the element that replaces it has an end
669  * address that is equal to or lower than that of the replaced
670  * element.  That property is necessary to guarantee that when
671  * searching for an element we end up at a position not higher than
672  * the one we're looking for (i.e. we either find the element directly
673  * or we end up to the left of it).
674  */
675 void
676 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
677 {
678         MonoJitInfoTable *table;
679         int chunk_pos, pos;
680         MonoJitInfoTableChunk *chunk;
681         int num_elements;
682         int i;
683
684         g_assert (ji->method != NULL);
685
686         mono_domain_lock (domain);
687
688         ++mono_stats.jit_info_table_insert_count;
689
690         table = domain->jit_info_table;
691
692  restart:
693         chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
694         g_assert (chunk_pos < table->num_chunks);
695         chunk = table->chunks [chunk_pos];
696
697         if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
698                 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
699
700                 /* Debugging code, should be removed. */
701                 //jit_info_table_check (new_table);
702
703                 domain->jit_info_table = new_table;
704                 mono_memory_barrier ();
705                 domain->num_jit_info_tables++;
706                 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free);
707                 table = new_table;
708
709                 goto restart;
710         }
711
712         /* Debugging code, should be removed. */
713         //jit_info_table_check (table);
714
715         num_elements = chunk->num_elements;
716
717         pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
718
719         /* First we need to size up the chunk by one, by copying the
720            last item, or inserting the first one, if the table is
721            empty. */
722         if (num_elements > 0)
723                 chunk->data [num_elements] = chunk->data [num_elements - 1];
724         else
725                 chunk->data [0] = ji;
726         mono_memory_write_barrier ();
727         chunk->num_elements = ++num_elements;
728
729         /* Shift the elements up one by one. */
730         for (i = num_elements - 2; i >= pos; --i) {
731                 mono_memory_write_barrier ();
732                 chunk->data [i + 1] = chunk->data [i];
733         }
734
735         /* Now we have room and can insert the new item. */
736         mono_memory_write_barrier ();
737         chunk->data [pos] = ji;
738
739         /* Set the high code end address chunk entry. */
740         chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
741                 + chunk->data [chunk->num_elements - 1]->code_size;
742
743         /* Debugging code, should be removed. */
744         //jit_info_table_check (table);
745
746         mono_domain_unlock (domain);
747 }
748
749 static MonoJitInfo*
750 mono_jit_info_make_tombstone (MonoJitInfo *ji)
751 {
752         MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
753
754         tombstone->code_start = ji->code_start;
755         tombstone->code_size = ji->code_size;
756         tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
757
758         return tombstone;
759 }
760
761 /*
762  * LOCKING: domain lock
763  */
764 static void
765 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
766 {
767         if (domain->num_jit_info_tables <= 1) {
768                 /* Can it actually happen that we only have one table
769                    but ji is still hazardous? */
770                 mono_thread_hazardous_free_or_queue (ji, g_free);
771         } else {
772                 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
773         }
774 }
775
776 void
777 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
778 {
779         MonoJitInfoTable *table;
780         MonoJitInfoTableChunk *chunk;
781         gpointer start = ji->code_start;
782         int chunk_pos, pos;
783
784         mono_domain_lock (domain);
785         table = domain->jit_info_table;
786
787         ++mono_stats.jit_info_table_remove_count;
788
789         chunk_pos = jit_info_table_index (table, start);
790         g_assert (chunk_pos < table->num_chunks);
791
792         pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
793
794         do {
795                 chunk = table->chunks [chunk_pos];
796
797                 while (pos < chunk->num_elements) {
798                         if (chunk->data [pos] == ji)
799                                 goto found;
800
801                         g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
802                         g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
803                                 <= (guint8*)ji->code_start + ji->code_size);
804
805                         ++pos;
806                 }
807
808                 ++chunk_pos;
809                 pos = 0;
810         } while (chunk_pos < table->num_chunks);
811
812  found:
813         g_assert (chunk->data [pos] == ji);
814
815         chunk->data [pos] = mono_jit_info_make_tombstone (ji);
816
817         /* Debugging code, should be removed. */
818         //jit_info_table_check (table);
819
820         mono_jit_info_free_or_queue (domain, ji);
821
822         mono_domain_unlock (domain);
823 }
824
825 static MonoAotModuleInfoTable*
826 mono_aot_module_info_table_new (void)
827 {
828         return g_array_new (FALSE, FALSE, sizeof (gpointer));
829 }
830
831 static int
832 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
833 {
834         int left = 0, right = table->len;
835
836         while (left < right) {
837                 int pos = (left + right) / 2;
838                 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
839                 char *start = ainfo->start;
840                 char *end = ainfo->end;
841
842                 if (addr < start)
843                         right = pos;
844                 else if (addr >= end) 
845                         left = pos + 1;
846                 else
847                         return pos;
848         }
849
850         return left;
851 }
852
853 void
854 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
855 {
856         AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
857         int pos;
858
859         ainfo->image = image;
860         ainfo->start = start;
861         ainfo->end = end;
862
863         mono_appdomains_lock ();
864
865         if (!aot_modules)
866                 aot_modules = mono_aot_module_info_table_new ();
867
868         pos = aot_info_table_index (aot_modules, start);
869
870         g_array_insert_val (aot_modules, pos, ainfo);
871
872         mono_appdomains_unlock ();
873 }
874
875 static MonoImage*
876 mono_jit_info_find_aot_module (guint8* addr)
877 {
878         guint left = 0, right;
879
880         if (!aot_modules)
881                 return NULL;
882
883         mono_appdomains_lock ();
884
885         right = aot_modules->len;
886         while (left < right) {
887                 guint pos = (left + right) / 2;
888                 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
889
890                 if (addr < (guint8*)ai->start)
891                         right = pos;
892                 else if (addr >= (guint8*)ai->end)
893                         left = pos + 1;
894                 else {
895                         mono_appdomains_unlock ();
896                         return ai->image;
897                 }
898         }
899
900         mono_appdomains_unlock ();
901
902         return NULL;
903 }
904
905 void
906 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
907 {
908         jit_info_find_in_aot_func = func;
909 }
910
911 gpointer
912 mono_jit_info_get_code_start (MonoJitInfo* ji)
913 {
914         return ji->code_start;
915 }
916
917 int
918 mono_jit_info_get_code_size (MonoJitInfo* ji)
919 {
920         return ji->code_size;
921 }
922
923 MonoMethod*
924 mono_jit_info_get_method (MonoJitInfo* ji)
925 {
926         return ji->method;
927 }
928
929 static gpointer
930 jit_info_key_extract (gpointer value)
931 {
932         MonoJitInfo *info = (MonoJitInfo*)value;
933
934         return info->method;
935 }
936
937 static gpointer*
938 jit_info_next_value (gpointer value)
939 {
940         MonoJitInfo *info = (MonoJitInfo*)value;
941
942         return (gpointer*)&info->next_jit_code_hash;
943 }
944
945 void
946 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
947 {
948         mono_internal_hash_table_init (jit_code_hash,
949                                        mono_aligned_addr_hash,
950                                        jit_info_key_extract,
951                                        jit_info_next_value);
952 }
953
954 MonoGenericJitInfo*
955 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
956 {
957         if (ji->has_generic_jit_info)
958                 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
959         else
960                 return NULL;
961 }
962
963 /*
964  * mono_jit_info_get_generic_sharing_context:
965  * @ji: a jit info
966  *
967  * Returns the jit info's generic sharing context, or NULL if it
968  * doesn't have one.
969  */
970 MonoGenericSharingContext*
971 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
972 {
973         MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
974
975         if (gi)
976                 return gi->generic_sharing_context;
977         else
978                 return NULL;
979 }
980
981 /*
982  * mono_jit_info_set_generic_sharing_context:
983  * @ji: a jit info
984  * @gsctx: a generic sharing context
985  *
986  * Sets the jit info's generic sharing context.  The jit info must
987  * have memory allocated for the context.
988  */
989 void
990 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
991 {
992         MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
993
994         g_assert (gi);
995
996         gi->generic_sharing_context = gsctx;
997 }
998
999 /**
1000  * mono_string_equal:
1001  * @s1: First string to compare
1002  * @s2: Second string to compare
1003  *
1004  * Returns FALSE if the strings differ.
1005  */
1006 gboolean
1007 mono_string_equal (MonoString *s1, MonoString *s2)
1008 {
1009         int l1 = mono_string_length (s1);
1010         int l2 = mono_string_length (s2);
1011
1012         if (s1 == s2)
1013                 return TRUE;
1014         if (l1 != l2)
1015                 return FALSE;
1016
1017         return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0; 
1018 }
1019
1020 /**
1021  * mono_string_hash:
1022  * @s: the string to hash
1023  *
1024  * Returns the hash for the string.
1025  */
1026 guint
1027 mono_string_hash (MonoString *s)
1028 {
1029         const guint16 *p = mono_string_chars (s);
1030         int i, len = mono_string_length (s);
1031         guint h = 0;
1032
1033         for (i = 0; i < len; i++) {
1034                 h = (h << 5) - h + *p;
1035                 p++;
1036         }
1037
1038         return h;       
1039 }
1040
1041 static gboolean
1042 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1043 {
1044         int len = GPOINTER_TO_INT (s1 [0]);
1045         if (len != GPOINTER_TO_INT (s2 [0]))
1046                 return FALSE;
1047
1048         return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0; 
1049 }
1050
1051 static guint
1052 mono_ptrarray_hash (gpointer *s)
1053 {
1054         int i;
1055         int len = GPOINTER_TO_INT (s [0]);
1056         guint hash = 0;
1057         
1058         for (i = 1; i < len; i++)
1059                 hash += GPOINTER_TO_UINT (s [i]);
1060
1061         return hash;    
1062 }
1063
1064 /*
1065  * Allocate an id for domain and set domain->domain_id.
1066  * LOCKING: must be called while holding appdomains_mutex.
1067  * We try to assign low numbers to the domain, so it can be used
1068  * as an index in data tables to lookup domain-specific info
1069  * with minimal memory overhead. We also try not to reuse the
1070  * same id too quickly (to help debugging).
1071  */
1072 static int
1073 domain_id_alloc (MonoDomain *domain)
1074 {
1075         int id = -1, i;
1076         if (!appdomains_list) {
1077                 appdomain_list_size = 2;
1078                 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1079         }
1080         for (i = appdomain_next; i < appdomain_list_size; ++i) {
1081                 if (!appdomains_list [i]) {
1082                         id = i;
1083                         break;
1084                 }
1085         }
1086         if (id == -1) {
1087                 for (i = 0; i < appdomain_next; ++i) {
1088                         if (!appdomains_list [i]) {
1089                                 id = i;
1090                                 break;
1091                         }
1092                 }
1093         }
1094         if (id == -1) {
1095                 MonoDomain **new_list;
1096                 int new_size = appdomain_list_size * 2;
1097                 if (new_size >= (1 << 16))
1098                         g_assert_not_reached ();
1099                 id = appdomain_list_size;
1100                 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1101                 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1102                 mono_gc_free_fixed (appdomains_list);
1103                 appdomains_list = new_list;
1104                 appdomain_list_size = new_size;
1105         }
1106         domain->domain_id = id;
1107         appdomains_list [id] = domain;
1108         appdomain_next++;
1109         if (appdomain_next > appdomain_list_size)
1110                 appdomain_next = 0;
1111         return id;
1112 }
1113
1114 static guint32 domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1115 static gpointer domain_gc_desc = NULL;
1116 static guint32 domain_shadow_serial = 0L;
1117
1118 MonoDomain *
1119 mono_domain_create (void)
1120 {
1121         MonoDomain *domain;
1122         guint32 shadow_serial;
1123   
1124         mono_appdomains_lock ();
1125         shadow_serial = domain_shadow_serial++;
1126   
1127         if (!domain_gc_desc) {
1128                 unsigned int i, bit = 0;
1129                 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1130                         bit = i / sizeof (gpointer);
1131                         domain_gc_bitmap [bit / 32] |= 1 << (bit % 32);
1132                 }
1133                 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1134         }
1135         mono_appdomains_unlock ();
1136
1137         domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1138         domain->shadow_serial = shadow_serial;
1139         domain->domain = NULL;
1140         domain->setup = NULL;
1141         domain->friendly_name = NULL;
1142         domain->search_path = NULL;
1143
1144         mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1145
1146         domain->mp = mono_mempool_new ();
1147         domain->code_mp = mono_code_manager_new ();
1148         domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1149         domain->domain_assemblies = NULL;
1150         domain->class_vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1151         domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1152         domain->static_data_array = NULL;
1153         mono_jit_code_hash_init (&domain->jit_code_hash);
1154         domain->ldstr_table = mono_g_hash_table_new ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal);
1155         domain->num_jit_info_tables = 1;
1156         domain->jit_info_table = jit_info_table_new (domain);
1157         domain->jit_info_free_queue = NULL;
1158         domain->class_init_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1159         domain->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1160         domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1161         domain->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1162         domain->delegate_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1163
1164         InitializeCriticalSection (&domain->lock);
1165         InitializeCriticalSection (&domain->assemblies_lock);
1166
1167         domain->shared_generics_hash = NULL;
1168         domain->method_rgctx_hash = NULL;
1169
1170         mono_appdomains_lock ();
1171         domain_id_alloc (domain);
1172         mono_appdomains_unlock ();
1173
1174         mono_debug_domain_create (domain);
1175
1176         mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1177         
1178         return domain;
1179 }
1180
1181 /**
1182  * mono_init_internal:
1183  * 
1184  * Creates the initial application domain and initializes the mono_defaults
1185  * structure.
1186  * This function is guaranteed to not run any IL code.
1187  * If exe_filename is not NULL, the method will determine the required runtime
1188  * from the exe configuration file or the version PE field.
1189  * If runtime_version is not NULL, that runtime version will be used.
1190  * Either exe_filename or runtime_version must be provided.
1191  *
1192  * Returns: the initial domain.
1193  */
1194 static MonoDomain *
1195 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1196 {
1197         static MonoDomain *domain = NULL;
1198         MonoAssembly *ass = NULL;
1199         MonoImageOpenStatus status = MONO_IMAGE_OK;
1200         const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1201         int n;
1202
1203         if (domain)
1204                 g_assert_not_reached ();
1205
1206 #if defined(PLATFORM_WIN32) && !defined(_WIN64)
1207         mono_load_coree (exe_filename);
1208 #endif
1209
1210         mono_perfcounters_init ();
1211
1212         mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1213         mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1214         mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1215
1216         mono_gc_base_init ();
1217
1218         appdomain_thread_id = TlsAlloc ();
1219
1220         InitializeCriticalSection (&appdomains_mutex);
1221
1222         mono_metadata_init ();
1223         mono_raw_buffer_init ();
1224         mono_images_init ();
1225         mono_assemblies_init ();
1226         mono_classes_init ();
1227         mono_loader_init ();
1228         mono_reflection_init ();
1229
1230         /* FIXME: When should we release this memory? */
1231         MONO_GC_REGISTER_ROOT (appdomains_list);
1232
1233         domain = mono_domain_create ();
1234         mono_root_domain = domain;
1235
1236         SET_APPDOMAIN (domain);
1237         
1238         /* Get a list of runtimes supported by the exe */
1239         if (exe_filename != NULL) {
1240                 /*
1241                  * This function will load the exe file as a MonoImage. We need to close it, but
1242                  * that would mean it would be reloaded later. So instead, we save it to
1243                  * exe_image, and close it during shutdown.
1244                  */
1245                 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1246 #ifdef PLATFORM_WIN32
1247                 if (!exe_image) {
1248                         exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1249                         if (!exe_image)
1250                                 exe_image = mono_image_open (exe_filename, NULL);
1251                 }
1252                 mono_fixup_exe_image (exe_image);
1253 #endif
1254         } else if (runtime_version != NULL) {
1255                 runtimes [0] = get_runtime_by_version (runtime_version);
1256                 runtimes [1] = NULL;
1257         }
1258
1259         if (runtimes [0] == NULL) {
1260                 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1261                 runtimes [0] = default_runtime;
1262                 runtimes [1] = NULL;
1263                 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1264                 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1265         }
1266
1267         /* The selected runtime will be the first one for which there is a mscrolib.dll */
1268         for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1269                 current_runtime = runtimes [n];
1270                 ass = mono_assembly_load_corlib (current_runtime, &status);
1271                 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1272                         break;
1273
1274         }
1275         
1276         /* Now that we have a runtime, set the policy for unhandled exceptions */
1277         if (mono_get_runtime_info ()->framework_version [0] < '2') {
1278                 mono_runtime_unhandled_exception_policy_set (MONO_UNHANLED_POLICY_LEGACY);
1279         }
1280
1281         if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1282                 switch (status){
1283                 case MONO_IMAGE_ERROR_ERRNO: {
1284                         char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1285                         g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1286                         g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1287                         g_free (corlib_file);
1288                         break;
1289                 }
1290                 case MONO_IMAGE_IMAGE_INVALID:
1291                         g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1292                                  mono_assembly_getrootdir ());
1293                         break;
1294                 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1295                         g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1296                                  mono_assembly_getrootdir ());
1297                         break;
1298                 case MONO_IMAGE_OK:
1299                         /* to suppress compiler warning */
1300                         break;
1301                 }
1302                 
1303                 exit (1);
1304         }
1305         mono_defaults.corlib = mono_assembly_get_image (ass);
1306
1307         mono_defaults.object_class = mono_class_from_name (
1308                 mono_defaults.corlib, "System", "Object");
1309         g_assert (mono_defaults.object_class != 0);
1310
1311         mono_defaults.void_class = mono_class_from_name (
1312                 mono_defaults.corlib, "System", "Void");
1313         g_assert (mono_defaults.void_class != 0);
1314
1315         mono_defaults.boolean_class = mono_class_from_name (
1316                 mono_defaults.corlib, "System", "Boolean");
1317         g_assert (mono_defaults.boolean_class != 0);
1318
1319         mono_defaults.byte_class = mono_class_from_name (
1320                 mono_defaults.corlib, "System", "Byte");
1321         g_assert (mono_defaults.byte_class != 0);
1322
1323         mono_defaults.sbyte_class = mono_class_from_name (
1324                 mono_defaults.corlib, "System", "SByte");
1325         g_assert (mono_defaults.sbyte_class != 0);
1326
1327         mono_defaults.int16_class = mono_class_from_name (
1328                 mono_defaults.corlib, "System", "Int16");
1329         g_assert (mono_defaults.int16_class != 0);
1330
1331         mono_defaults.uint16_class = mono_class_from_name (
1332                 mono_defaults.corlib, "System", "UInt16");
1333         g_assert (mono_defaults.uint16_class != 0);
1334
1335         mono_defaults.int32_class = mono_class_from_name (
1336                 mono_defaults.corlib, "System", "Int32");
1337         g_assert (mono_defaults.int32_class != 0);
1338
1339         mono_defaults.uint32_class = mono_class_from_name (
1340                 mono_defaults.corlib, "System", "UInt32");
1341         g_assert (mono_defaults.uint32_class != 0);
1342
1343         mono_defaults.uint_class = mono_class_from_name (
1344                 mono_defaults.corlib, "System", "UIntPtr");
1345         g_assert (mono_defaults.uint_class != 0);
1346
1347         mono_defaults.int_class = mono_class_from_name (
1348                 mono_defaults.corlib, "System", "IntPtr");
1349         g_assert (mono_defaults.int_class != 0);
1350
1351         mono_defaults.int64_class = mono_class_from_name (
1352                 mono_defaults.corlib, "System", "Int64");
1353         g_assert (mono_defaults.int64_class != 0);
1354
1355         mono_defaults.uint64_class = mono_class_from_name (
1356                 mono_defaults.corlib, "System", "UInt64");
1357         g_assert (mono_defaults.uint64_class != 0);
1358
1359         mono_defaults.single_class = mono_class_from_name (
1360                 mono_defaults.corlib, "System", "Single");
1361         g_assert (mono_defaults.single_class != 0);
1362
1363         mono_defaults.double_class = mono_class_from_name (
1364                 mono_defaults.corlib, "System", "Double");
1365         g_assert (mono_defaults.double_class != 0);
1366
1367         mono_defaults.char_class = mono_class_from_name (
1368                 mono_defaults.corlib, "System", "Char");
1369         g_assert (mono_defaults.char_class != 0);
1370
1371         mono_defaults.string_class = mono_class_from_name (
1372                 mono_defaults.corlib, "System", "String");
1373         g_assert (mono_defaults.string_class != 0);
1374
1375         mono_defaults.enum_class = mono_class_from_name (
1376                 mono_defaults.corlib, "System", "Enum");
1377         g_assert (mono_defaults.enum_class != 0);
1378
1379         mono_defaults.array_class = mono_class_from_name (
1380                 mono_defaults.corlib, "System", "Array");
1381         g_assert (mono_defaults.array_class != 0);
1382
1383         mono_defaults.delegate_class = mono_class_from_name (
1384                 mono_defaults.corlib, "System", "Delegate");
1385         g_assert (mono_defaults.delegate_class != 0 );
1386
1387         mono_defaults.multicastdelegate_class = mono_class_from_name (
1388                 mono_defaults.corlib, "System", "MulticastDelegate");
1389         g_assert (mono_defaults.multicastdelegate_class != 0 );
1390
1391         mono_defaults.asyncresult_class = mono_class_from_name (
1392                 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", 
1393                 "AsyncResult");
1394         g_assert (mono_defaults.asyncresult_class != 0 );
1395
1396         mono_defaults.waithandle_class = mono_class_from_name (
1397                 mono_defaults.corlib, "System.Threading", "WaitHandle");
1398         g_assert (mono_defaults.waithandle_class != 0 );
1399
1400         mono_defaults.typehandle_class = mono_class_from_name (
1401                 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1402         g_assert (mono_defaults.typehandle_class != 0);
1403
1404         mono_defaults.methodhandle_class = mono_class_from_name (
1405                 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1406         g_assert (mono_defaults.methodhandle_class != 0);
1407
1408         mono_defaults.fieldhandle_class = mono_class_from_name (
1409                 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1410         g_assert (mono_defaults.fieldhandle_class != 0);
1411
1412         mono_defaults.systemtype_class = mono_class_from_name (
1413                 mono_defaults.corlib, "System", "Type");
1414         g_assert (mono_defaults.systemtype_class != 0);
1415
1416         mono_defaults.monotype_class = mono_class_from_name (
1417                 mono_defaults.corlib, "System", "MonoType");
1418         g_assert (mono_defaults.monotype_class != 0);
1419
1420         mono_defaults.exception_class = mono_class_from_name (
1421                 mono_defaults.corlib, "System", "Exception");
1422         g_assert (mono_defaults.exception_class != 0);
1423
1424         mono_defaults.threadabortexception_class = mono_class_from_name (
1425                 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1426         g_assert (mono_defaults.threadabortexception_class != 0);
1427
1428         mono_defaults.thread_class = mono_class_from_name (
1429                 mono_defaults.corlib, "System.Threading", "Thread");
1430         g_assert (mono_defaults.thread_class != 0);
1431
1432         mono_defaults.appdomain_class = mono_class_from_name (
1433                 mono_defaults.corlib, "System", "AppDomain");
1434         g_assert (mono_defaults.appdomain_class != 0);
1435
1436         mono_defaults.transparent_proxy_class = mono_class_from_name (
1437                 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1438         g_assert (mono_defaults.transparent_proxy_class != 0);
1439
1440         mono_defaults.real_proxy_class = mono_class_from_name (
1441                 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1442         g_assert (mono_defaults.real_proxy_class != 0);
1443
1444         mono_defaults.mono_method_message_class = mono_class_from_name (
1445                 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1446         g_assert (mono_defaults.mono_method_message_class != 0);
1447
1448         mono_defaults.field_info_class = mono_class_from_name (
1449                 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1450         g_assert (mono_defaults.field_info_class != 0);
1451
1452         mono_defaults.method_info_class = mono_class_from_name (
1453                 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1454         g_assert (mono_defaults.method_info_class != 0);
1455
1456         mono_defaults.stringbuilder_class = mono_class_from_name (
1457                 mono_defaults.corlib, "System.Text", "StringBuilder");
1458         g_assert (mono_defaults.stringbuilder_class != 0);
1459
1460         mono_defaults.math_class = mono_class_from_name (
1461                 mono_defaults.corlib, "System", "Math");
1462         g_assert (mono_defaults.math_class != 0);
1463
1464         mono_defaults.stack_frame_class = mono_class_from_name (
1465                 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1466         g_assert (mono_defaults.stack_frame_class != 0);
1467
1468         mono_defaults.stack_trace_class = mono_class_from_name (
1469                 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1470         g_assert (mono_defaults.stack_trace_class != 0);
1471
1472         mono_defaults.marshal_class = mono_class_from_name (
1473                 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1474         g_assert (mono_defaults.marshal_class != 0);
1475
1476         mono_defaults.iserializeable_class = mono_class_from_name (
1477                 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1478         g_assert (mono_defaults.iserializeable_class != 0);
1479
1480         mono_defaults.serializationinfo_class = mono_class_from_name (
1481                 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1482         g_assert (mono_defaults.serializationinfo_class != 0);
1483
1484         mono_defaults.streamingcontext_class = mono_class_from_name (
1485                 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1486         g_assert (mono_defaults.streamingcontext_class != 0);
1487
1488         mono_defaults.typed_reference_class =  mono_class_from_name (
1489                 mono_defaults.corlib, "System", "TypedReference");
1490         g_assert (mono_defaults.typed_reference_class != 0);
1491
1492         mono_defaults.argumenthandle_class =  mono_class_from_name (
1493                 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1494         g_assert (mono_defaults.argumenthandle_class != 0);
1495
1496         mono_defaults.marshalbyrefobject_class =  mono_class_from_name (
1497                 mono_defaults.corlib, "System", "MarshalByRefObject");
1498         g_assert (mono_defaults.marshalbyrefobject_class != 0);
1499
1500         mono_defaults.monitor_class =  mono_class_from_name (
1501                 mono_defaults.corlib, "System.Threading", "Monitor");
1502         g_assert (mono_defaults.monitor_class != 0);
1503
1504         mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1505                 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1506         g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1507
1508         mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1509                 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1510
1511         mono_defaults.executioncontext_class = mono_class_from_name (
1512                 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1513
1514         mono_defaults.internals_visible_class = mono_class_from_name (
1515                 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1516
1517         /*
1518          * mscorlib needs a little help, only now it can load its friends list (after we have
1519          * loaded the InternalsVisibleToAttribute), load it now
1520          */
1521         mono_assembly_load_friends (ass);
1522         
1523         mono_defaults.safehandle_class = mono_class_from_name (
1524                 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1525
1526         mono_defaults.handleref_class = mono_class_from_name (
1527                 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1528
1529         mono_defaults.attribute_class = mono_class_from_name (
1530                 mono_defaults.corlib, "System", "Attribute");
1531
1532         mono_defaults.customattribute_data_class = mono_class_from_name (
1533                 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1534
1535         /* these are initialized lazily when COM features are used */
1536         mono_defaults.variant_class = NULL;
1537         mono_defaults.com_object_class = NULL;
1538         mono_defaults.com_interop_proxy_class = NULL;
1539         mono_defaults.iunknown_class = NULL;
1540         mono_defaults.idispatch_class = NULL;
1541
1542         /*
1543          * Note that mono_defaults.generic_*_class is only non-NULL if we're
1544          * using the 2.0 corlib.
1545          */
1546         mono_class_init (mono_defaults.array_class);
1547         mono_defaults.generic_nullable_class = mono_class_from_name (
1548                 mono_defaults.corlib, "System", "Nullable`1");
1549         mono_defaults.generic_ilist_class = mono_class_from_name (
1550                 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1551
1552         domain->friendly_name = g_path_get_basename (filename);
1553
1554         _mono_debug_init_corlib (domain);
1555
1556         return domain;
1557 }
1558
1559 /**
1560  * mono_init:
1561  * 
1562  * Creates the initial application domain and initializes the mono_defaults
1563  * structure.
1564  * This function is guaranteed to not run any IL code.
1565  * The runtime is initialized using the default runtime version.
1566  *
1567  * Returns: the initial domain.
1568  */
1569 MonoDomain *
1570 mono_init (const char *domain_name)
1571 {
1572         return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1573 }
1574
1575 /**
1576  * mono_init_from_assembly:
1577  * 
1578  * Creates the initial application domain and initializes the mono_defaults
1579  * structure.
1580  * This function is guaranteed to not run any IL code.
1581  * The runtime is initialized using the runtime version required by the
1582  * provided executable. The version is determined by looking at the exe 
1583  * configuration file and the version PE field)
1584  *
1585  * Returns: the initial domain.
1586  */
1587 MonoDomain *
1588 mono_init_from_assembly (const char *domain_name, const char *filename)
1589 {
1590         return mono_init_internal (domain_name, filename, NULL);
1591 }
1592
1593 /**
1594  * mono_init_version:
1595  * 
1596  * Creates the initial application domain and initializes the mono_defaults
1597  * structure.
1598  * This function is guaranteed to not run any IL code.
1599  * The runtime is initialized using the provided rutime version.
1600  *
1601  * Returns: the initial domain.
1602  */
1603 MonoDomain *
1604 mono_init_version (const char *domain_name, const char *version)
1605 {
1606         return mono_init_internal (domain_name, NULL, version);
1607 }
1608
1609 /**
1610  * mono_init_com_types:
1611  *
1612  * Initializes all types needed for COM Interop in mono_defaults structure. 
1613  */
1614 void 
1615 mono_init_com_types (void)
1616 {
1617         static gboolean initialized = FALSE;
1618
1619         if (initialized)
1620                 return;
1621         
1622         /* FIXME: do I need some threading protection here */
1623
1624         g_assert (mono_defaults.corlib);
1625
1626         mono_defaults.variant_class = mono_class_from_name (
1627                 mono_defaults.corlib, "System", "Variant");
1628         g_assert (mono_defaults.variant_class != 0);
1629
1630         mono_defaults.com_object_class = mono_class_from_name (
1631                 mono_defaults.corlib, "System", "__ComObject");
1632         g_assert (mono_defaults.com_object_class != 0);
1633
1634         mono_defaults.com_interop_proxy_class = mono_class_from_name (
1635                 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1636         g_assert (mono_defaults.com_interop_proxy_class != 0);
1637
1638         mono_defaults.iunknown_class = mono_class_from_name (
1639                 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1640         g_assert (mono_defaults.iunknown_class != 0);
1641
1642         mono_defaults.idispatch_class = mono_class_from_name (
1643                 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1644         g_assert (mono_defaults.idispatch_class != 0);
1645
1646         initialized = TRUE;
1647 }
1648
1649 /**
1650  * mono_cleanup:
1651  *
1652  * Cleans up all metadata modules. 
1653  */
1654 void
1655 mono_cleanup (void)
1656 {
1657         mono_close_exe_image ();
1658
1659         mono_loader_cleanup ();
1660         mono_classes_cleanup ();
1661         mono_assemblies_cleanup ();
1662         mono_images_cleanup ();
1663         mono_debug_cleanup ();
1664         mono_raw_buffer_cleanup ();
1665         mono_metadata_cleanup ();
1666
1667         TlsFree (appdomain_thread_id);
1668         DeleteCriticalSection (&appdomains_mutex);
1669 }
1670
1671 void
1672 mono_close_exe_image (void)
1673 {
1674         if (exe_image)
1675                 mono_image_close (exe_image);
1676 }
1677
1678 /**
1679  * mono_get_root_domain:
1680  *
1681  * The root AppDomain is the initial domain created by the runtime when it is
1682  * initialized.  Programs execute on this AppDomain, but can create new ones
1683  * later.   Currently there is no unmanaged API to create new AppDomains, this
1684  * must be done from managed code.
1685  *
1686  * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1687  */
1688 MonoDomain*
1689 mono_get_root_domain (void)
1690 {
1691         return mono_root_domain;
1692 }
1693
1694 /**
1695  * mono_domain_get:
1696  *
1697  * Returns: the current domain, to obtain the root domain use
1698  * mono_get_root_domain().
1699  */
1700 MonoDomain *
1701 mono_domain_get ()
1702 {
1703         return GET_APPDOMAIN ();
1704 }
1705
1706 /**
1707  * mono_domain_set_internal:
1708  * @domain: the new domain
1709  *
1710  * Sets the current domain to @domain.
1711  */
1712 void
1713 mono_domain_set_internal (MonoDomain *domain)
1714 {
1715         SET_APPDOMAIN (domain);
1716         SET_APPCONTEXT (domain->default_context);
1717 }
1718
1719 void
1720 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1721 {
1722         int i, size;
1723         MonoDomain **copy;
1724
1725         /*
1726          * Create a copy of the data to avoid calling the user callback
1727          * inside the lock because that could lead to deadlocks.
1728          * We can do this because this function is not perf. critical.
1729          */
1730         mono_appdomains_lock ();
1731         size = appdomain_list_size;
1732         copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1733         memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1734         mono_appdomains_unlock ();
1735
1736         for (i = 0; i < size; ++i) {
1737                 if (copy [i])
1738                         func (copy [i], user_data);
1739         }
1740
1741         mono_gc_free_fixed (copy);
1742 }
1743
1744 /**
1745  * mono_domain_assembly_open:
1746  * @domain: the application domain
1747  * @name: file name of the assembly
1748  *
1749  * fixme: maybe we should integrate this with mono_assembly_open ??
1750  */
1751 MonoAssembly *
1752 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1753 {
1754         MonoAssembly *ass;
1755         GSList *tmp;
1756
1757         mono_domain_assemblies_lock (domain);
1758         for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1759                 ass = tmp->data;
1760                 if (strcmp (name, ass->aname.name) == 0) {
1761                         mono_domain_assemblies_unlock (domain);
1762                         return ass;
1763                 }
1764         }
1765         mono_domain_assemblies_unlock (domain);
1766
1767         if (!(ass = mono_assembly_open (name, NULL)))
1768                 return NULL;
1769
1770         return ass;
1771 }
1772
1773 MonoJitInfo*
1774 mono_domain_lookup_shared_generic (MonoDomain *domain, MonoMethod *method)
1775 {
1776         if (!domain->shared_generics_hash)
1777                 return NULL;
1778
1779         return g_hash_table_lookup (domain->shared_generics_hash, method);
1780 }
1781
1782 void
1783 mono_domain_register_shared_generic (MonoDomain *domain, MonoMethod *method, MonoJitInfo *jit_info)
1784 {
1785         if (!domain->shared_generics_hash)
1786                 domain->shared_generics_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1787
1788         g_assert (domain->shared_generics_hash);
1789
1790         g_hash_table_insert (domain->shared_generics_hash, method, jit_info);
1791 }
1792
1793 static void
1794 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
1795 {
1796         MonoJitDynamicMethodInfo *di = value;
1797         mono_code_manager_destroy (di->code_mp);
1798         g_free (di);
1799 }
1800
1801 static void
1802 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
1803 {
1804         g_slist_free (value);
1805 }
1806
1807 void
1808 mono_domain_free (MonoDomain *domain, gboolean force)
1809 {
1810         int code_size, code_alloc;
1811         GSList *tmp;
1812         if ((domain == mono_root_domain) && !force) {
1813                 g_warning ("cant unload root domain");
1814                 return;
1815         }
1816
1817         mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1818
1819         mono_debug_domain_unload (domain);
1820
1821         mono_appdomains_lock ();
1822         appdomains_list [domain->domain_id] = NULL;
1823         mono_appdomains_unlock ();
1824
1825         /* FIXME: free delegate_hash_table when it's used */
1826         if (domain->search_path) {
1827                 g_strfreev (domain->search_path);
1828                 domain->search_path = NULL;
1829         }
1830         domain->create_proxy_for_type_method = NULL;
1831         domain->private_invoke_method = NULL;
1832         domain->default_context = NULL;
1833         domain->out_of_memory_ex = NULL;
1834         domain->null_reference_ex = NULL;
1835         domain->stack_overflow_ex = NULL;
1836         domain->entry_assembly = NULL;
1837         /* must do this early as it accesses fields and types */
1838         if (domain->special_static_fields) {
1839                 mono_alloc_special_static_data_free (domain->special_static_fields);
1840                 g_hash_table_destroy (domain->special_static_fields);
1841                 domain->special_static_fields = NULL;
1842         }
1843         for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1844                 MonoAssembly *ass = tmp->data;
1845                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s %p, assembly %s %p, refcount=%d\n", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count);
1846                 mono_assembly_close (ass);
1847         }
1848         g_slist_free (domain->domain_assemblies);
1849         domain->domain_assemblies = NULL;
1850
1851         g_free (domain->friendly_name);
1852         domain->friendly_name = NULL;
1853         mono_g_hash_table_destroy (domain->env);
1854         domain->env = NULL;
1855         g_hash_table_destroy (domain->class_vtable_hash);
1856         domain->class_vtable_hash = NULL;
1857         g_hash_table_destroy (domain->proxy_vtable_hash);
1858         domain->proxy_vtable_hash = NULL;
1859         if (domain->static_data_array) {
1860                 mono_gc_free_fixed (domain->static_data_array);
1861                 domain->static_data_array = NULL;
1862         }
1863         mono_internal_hash_table_destroy (&domain->jit_code_hash);
1864         if (domain->dynamic_code_hash) {
1865                 g_hash_table_foreach (domain->dynamic_code_hash, dynamic_method_info_free, NULL);
1866                 g_hash_table_destroy (domain->dynamic_code_hash);
1867                 domain->dynamic_code_hash = NULL;
1868         }
1869         mono_g_hash_table_destroy (domain->ldstr_table);
1870         domain->ldstr_table = NULL;
1871
1872         /*
1873          * There might still be jit info tables of this domain which
1874          * are not freed.  Since the domain cannot be in use anymore,
1875          * this will free them.
1876          */
1877         mono_thread_hazardous_try_free_all ();
1878         g_assert (domain->num_jit_info_tables == 1);
1879         jit_info_table_free (domain->jit_info_table);
1880         domain->jit_info_table = NULL;
1881         g_assert (!domain->jit_info_free_queue);
1882
1883         /* collect statistics */
1884         code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
1885         total_domain_code_alloc += code_alloc;
1886         max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
1887         max_domain_code_size = MAX (max_domain_code_size, code_size);
1888
1889 #ifdef DEBUG_DOMAIN_UNLOAD
1890         mono_mempool_invalidate (domain->mp);
1891         mono_code_manager_invalidate (domain->code_mp);
1892 #else
1893         mono_mempool_destroy (domain->mp);
1894         domain->mp = NULL;
1895         mono_code_manager_destroy (domain->code_mp);
1896         domain->code_mp = NULL;
1897 #endif  
1898         if (domain->jump_target_hash) {
1899                 g_hash_table_foreach (domain->jump_target_hash, delete_jump_list, NULL);
1900                 g_hash_table_destroy (domain->jump_target_hash);
1901                 domain->jump_target_hash = NULL;
1902         }
1903         if (domain->type_hash) {
1904                 mono_g_hash_table_destroy (domain->type_hash);
1905                 domain->type_hash = NULL;
1906         }
1907         if (domain->refobject_hash) {
1908                 mono_g_hash_table_destroy (domain->refobject_hash);
1909                 domain->refobject_hash = NULL;
1910         }
1911         if (domain->type_init_exception_hash) {
1912                 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1913                 domain->type_init_exception_hash = NULL;
1914         }
1915         g_hash_table_destroy (domain->class_init_trampoline_hash);
1916         domain->class_init_trampoline_hash = NULL;
1917         g_hash_table_destroy (domain->jump_trampoline_hash);
1918         domain->jump_trampoline_hash = NULL;
1919         g_hash_table_destroy (domain->finalizable_objects_hash);
1920         domain->finalizable_objects_hash = NULL;
1921         g_hash_table_destroy (domain->jit_trampoline_hash);
1922         domain->jit_trampoline_hash = NULL;
1923         g_hash_table_destroy (domain->delegate_trampoline_hash);
1924         domain->delegate_trampoline_hash = NULL;
1925         if (domain->shared_generics_hash) {
1926                 g_hash_table_destroy (domain->shared_generics_hash);
1927                 domain->shared_generics_hash = NULL;
1928         }
1929         if (domain->method_rgctx_hash) {
1930                 g_hash_table_destroy (domain->method_rgctx_hash);
1931                 domain->method_rgctx_hash = NULL;
1932         }
1933
1934         DeleteCriticalSection (&domain->assemblies_lock);
1935         DeleteCriticalSection (&domain->lock);
1936         domain->setup = NULL;
1937
1938         /* FIXME: anything else required ? */
1939
1940         mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
1941
1942         mono_gc_free_fixed (domain);
1943
1944         if ((domain == mono_root_domain))
1945                 mono_root_domain = NULL;
1946 }
1947
1948 /**
1949  * mono_domain_get_id:
1950  * @domainid: the ID
1951  *
1952  * Returns: the a domain for a specific domain id.
1953  */
1954 MonoDomain * 
1955 mono_domain_get_by_id (gint32 domainid) 
1956 {
1957         MonoDomain * domain;
1958
1959         mono_appdomains_lock ();
1960         if (domainid < appdomain_list_size)
1961                 domain = appdomains_list [domainid];
1962         else
1963                 domain = NULL;
1964         mono_appdomains_unlock ();
1965
1966         return domain;
1967 }
1968
1969 gint32
1970 mono_domain_get_id (MonoDomain *domain)
1971 {
1972         return domain->domain_id;
1973 }
1974
1975 void 
1976 mono_context_set (MonoAppContext * new_context)
1977 {
1978         SET_APPCONTEXT (new_context);
1979 }
1980
1981 MonoAppContext * 
1982 mono_context_get (void)
1983 {
1984         return GET_APPCONTEXT ();
1985 }
1986
1987 /* LOCKING: the caller holds the lock for this domain */
1988 void
1989 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
1990 {
1991         /* The first entry in the array is the index of the next free slot
1992          * and the total size of the array
1993          */
1994         int next;
1995         if (domain->static_data_array) {
1996                 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
1997                 next = GPOINTER_TO_INT (domain->static_data_array [0]);
1998                 if (next >= size) {
1999                         gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), NULL);
2000                         memcpy (new_array, domain->static_data_array, sizeof (gpointer) * size);
2001                         size *= 2;
2002                         new_array [1] = GINT_TO_POINTER (size);
2003                         mono_gc_free_fixed (domain->static_data_array);
2004                         domain->static_data_array = new_array;
2005                 }
2006         } else {
2007                 int size = 32;
2008                 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, NULL);
2009                 next = 2;
2010                 new_array [0] = GINT_TO_POINTER (next);
2011                 new_array [1] = GINT_TO_POINTER (size);
2012                 domain->static_data_array = new_array;
2013         }
2014         domain->static_data_array [next++] = data;
2015         domain->static_data_array [0] = GINT_TO_POINTER (next);
2016 }
2017
2018 MonoImage*
2019 mono_get_corlib (void)
2020 {
2021         return mono_defaults.corlib;
2022 }
2023
2024 MonoClass*
2025 mono_get_object_class (void)
2026 {
2027         return mono_defaults.object_class;
2028 }
2029
2030 MonoClass*
2031 mono_get_byte_class (void)
2032 {
2033         return mono_defaults.byte_class;
2034 }
2035
2036 MonoClass*
2037 mono_get_void_class (void)
2038 {
2039         return mono_defaults.void_class;
2040 }
2041
2042 MonoClass*
2043 mono_get_boolean_class (void)
2044 {
2045         return mono_defaults.boolean_class;
2046 }
2047
2048 MonoClass*
2049 mono_get_sbyte_class (void)
2050 {
2051         return mono_defaults.sbyte_class;
2052 }
2053
2054 MonoClass*
2055 mono_get_int16_class (void)
2056 {
2057         return mono_defaults.int16_class;
2058 }
2059
2060 MonoClass*
2061 mono_get_uint16_class (void)
2062 {
2063         return mono_defaults.uint16_class;
2064 }
2065
2066 MonoClass*
2067 mono_get_int32_class (void)
2068 {
2069         return mono_defaults.int32_class;
2070 }
2071
2072 MonoClass*
2073 mono_get_uint32_class (void)
2074 {
2075         return mono_defaults.uint32_class;
2076 }
2077
2078 MonoClass*
2079 mono_get_intptr_class (void)
2080 {
2081         return mono_defaults.int_class;
2082 }
2083
2084 MonoClass*
2085 mono_get_uintptr_class (void)
2086 {
2087         return mono_defaults.uint_class;
2088 }
2089
2090 MonoClass*
2091 mono_get_int64_class (void)
2092 {
2093         return mono_defaults.int64_class;
2094 }
2095
2096 MonoClass*
2097 mono_get_uint64_class (void)
2098 {
2099         return mono_defaults.uint64_class;
2100 }
2101
2102 MonoClass*
2103 mono_get_single_class (void)
2104 {
2105         return mono_defaults.single_class;
2106 }
2107
2108 MonoClass*
2109 mono_get_double_class (void)
2110 {
2111         return mono_defaults.double_class;
2112 }
2113
2114 MonoClass*
2115 mono_get_char_class (void)
2116 {
2117         return mono_defaults.char_class;
2118 }
2119
2120 MonoClass*
2121 mono_get_string_class (void)
2122 {
2123         return mono_defaults.string_class;
2124 }
2125
2126 MonoClass*
2127 mono_get_enum_class (void)
2128 {
2129         return mono_defaults.enum_class;
2130 }
2131
2132 MonoClass*
2133 mono_get_array_class (void)
2134 {
2135         return mono_defaults.array_class;
2136 }
2137
2138 MonoClass*
2139 mono_get_thread_class (void)
2140 {
2141         return mono_defaults.thread_class;
2142 }
2143
2144 MonoClass*
2145 mono_get_exception_class (void)
2146 {
2147         return mono_defaults.exception_class;
2148 }
2149
2150
2151 static char* get_attribute_value (const gchar **attribute_names, 
2152                                         const gchar **attribute_values, 
2153                                         const char *att_name)
2154 {
2155         int n;
2156         for (n=0; attribute_names[n] != NULL; n++) {
2157                 if (strcmp (attribute_names[n], att_name) == 0)
2158                         return g_strdup (attribute_values[n]);
2159         }
2160         return NULL;
2161 }
2162
2163 static void start_element (GMarkupParseContext *context, 
2164                            const gchar         *element_name,
2165                            const gchar        **attribute_names,
2166                            const gchar        **attribute_values,
2167                            gpointer             user_data,
2168                            GError             **error)
2169 {
2170         AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2171         
2172         if (strcmp (element_name, "configuration") == 0) {
2173                 app_config->configuration_count++;
2174                 return;
2175         }
2176         if (strcmp (element_name, "startup") == 0) {
2177                 app_config->startup_count++;
2178                 return;
2179         }
2180         
2181         if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2182                 return;
2183         
2184         if (strcmp (element_name, "requiredRuntime") == 0) {
2185                 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2186         } else if (strcmp (element_name, "supportedRuntime") == 0) {
2187                 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2188                 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2189         }
2190 }
2191
2192 static void end_element   (GMarkupParseContext *context,
2193                            const gchar         *element_name,
2194                            gpointer             user_data,
2195                            GError             **error)
2196 {
2197         AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2198         
2199         if (strcmp (element_name, "configuration") == 0) {
2200                 app_config->configuration_count--;
2201         } else if (strcmp (element_name, "startup") == 0) {
2202                 app_config->startup_count--;
2203         }
2204 }
2205
2206 static const GMarkupParser 
2207 mono_parser = {
2208         start_element,
2209         end_element,
2210         NULL,
2211         NULL,
2212         NULL
2213 };
2214
2215 static AppConfigInfo *
2216 app_config_parse (const char *exe_filename)
2217 {
2218         AppConfigInfo *app_config;
2219         GMarkupParseContext *context;
2220         char *text;
2221         gsize len;
2222         struct stat buf;
2223         const char *bundled_config;
2224         char *config_filename;
2225
2226         bundled_config = mono_config_string_for_assembly_file (exe_filename);
2227
2228         if (bundled_config) {
2229                 text = g_strdup (bundled_config);
2230                 len = strlen (text);
2231         } else {
2232                 config_filename = g_strconcat (exe_filename, ".config", NULL);
2233
2234                 if (stat (config_filename, &buf) != 0) {
2235                         g_free (config_filename);
2236                         return NULL;
2237                 }
2238         
2239                 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2240                         g_free (config_filename);
2241                         return NULL;
2242                 }
2243                 g_free (config_filename);
2244         }
2245
2246         app_config = g_new0 (AppConfigInfo, 1);
2247
2248         context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2249         if (g_markup_parse_context_parse (context, text, len, NULL)) {
2250                 g_markup_parse_context_end_parse (context, NULL);
2251         }
2252         g_markup_parse_context_free (context);
2253         g_free (text);
2254         return app_config;
2255 }
2256
2257 static void 
2258 app_config_free (AppConfigInfo* app_config)
2259 {
2260         char *rt;
2261         GSList *list = app_config->supported_runtimes;
2262         while (list != NULL) {
2263                 rt = (char*)list->data;
2264                 g_free (rt);
2265                 list = g_slist_next (list);
2266         }
2267         g_slist_free (app_config->supported_runtimes);
2268         g_free (app_config->required_runtime);
2269         g_free (app_config);
2270 }
2271
2272
2273 static const MonoRuntimeInfo*
2274 get_runtime_by_version (const char *version)
2275 {
2276         int n;
2277         int max = G_N_ELEMENTS (supported_runtimes);
2278         
2279         for (n=0; n<max; n++) {
2280                 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2281                         return &supported_runtimes[n];
2282         }
2283         return NULL;
2284 }
2285
2286 static void
2287 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2288 {
2289         AppConfigInfo* app_config;
2290         char *version;
2291         const MonoRuntimeInfo* runtime = NULL;
2292         MonoImage *image = NULL;
2293         
2294         app_config = app_config_parse (exe_file);
2295         
2296         if (app_config != NULL) {
2297                 /* Check supportedRuntime elements, if none is supported, fail.
2298                  * If there are no such elements, look for a requiredRuntime element.
2299                  */
2300                 if (app_config->supported_runtimes != NULL) {
2301                         int n = 0;
2302                         GSList *list = app_config->supported_runtimes;
2303                         while (list != NULL) {
2304                                 version = (char*) list->data;
2305                                 runtime = get_runtime_by_version (version);
2306                                 if (runtime != NULL)
2307                                         runtimes [n++] = runtime;
2308                                 list = g_slist_next (list);
2309                         }
2310                         runtimes [n] = NULL;
2311                         app_config_free (app_config);
2312                         return;
2313                 }
2314                 
2315                 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2316                 if (app_config->required_runtime != NULL) {
2317                         runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2318                         runtimes [1] = NULL;
2319                         app_config_free (app_config);
2320                         return;
2321                 }
2322                 app_config_free (app_config);
2323         }
2324         
2325         /* Look for a runtime with the exact version */
2326         image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2327
2328         if (image == NULL)
2329                 image = mono_image_open (exe_file, NULL);
2330
2331         if (image == NULL) {
2332                 /* The image is wrong or the file was not found. In this case return
2333                  * a default runtime and leave to the initialization method the work of
2334                  * reporting the error.
2335                  */
2336                 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2337                 runtimes [1] = NULL;
2338                 return;
2339         }
2340
2341         *exe_image = image;
2342
2343         runtimes [0] = get_runtime_by_version (image->version);
2344         runtimes [1] = NULL;
2345 }
2346
2347
2348 /**
2349  * mono_get_runtime_info:
2350  *
2351  * Returns: the version of the current runtime instance.
2352  */
2353 const MonoRuntimeInfo*
2354 mono_get_runtime_info (void)
2355 {
2356         return current_runtime;
2357 }
2358
2359 gchar *
2360 mono_debugger_check_runtime_version (const char *filename)
2361 {
2362         const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2363         const MonoRuntimeInfo *rinfo;
2364         MonoImage *image;
2365
2366         get_runtimes_from_exe (filename, &image, runtimes);
2367         rinfo = runtimes [0];
2368
2369         if (!rinfo)
2370                 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2371
2372         if (rinfo != current_runtime)
2373                 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2374                                         "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2375                                         filename, rinfo->runtime_version);
2376
2377         return NULL;
2378 }