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