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