2 * domain.c: MonoDomain functions
5 * Dietmar Maurer (dietmar@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com)
18 #include <mono/metadata/gc-internal.h>
20 #include <mono/utils/mono-compiler.h>
21 #include <mono/utils/mono-logger-internal.h>
22 #include <mono/utils/mono-membar.h>
23 #include <mono/utils/mono-counters.h>
24 #include <mono/utils/hazard-pointer.h>
25 #include <mono/utils/mono-tls.h>
26 #include <mono/metadata/object.h>
27 #include <mono/metadata/object-internals.h>
28 #include <mono/metadata/domain-internals.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/assembly.h>
31 #include <mono/metadata/exception.h>
32 #include <mono/metadata/metadata-internals.h>
33 #include <mono/metadata/gc-internal.h>
34 #include <mono/metadata/appdomain.h>
35 #include <mono/metadata/mono-debug-debugger.h>
36 #include <mono/metadata/mono-config.h>
37 #include <mono/metadata/threads-types.h>
38 #include <metadata/threads.h>
39 #include <metadata/profiler-private.h>
40 #include <mono/metadata/coree.h>
42 /* #define DEBUG_DOMAIN_UNLOAD */
44 /* we need to use both the Tls* functions and __thread because
45 * some archs may generate faster jit code with one meachanism
46 * or the other (we used to do it because tls slots were GC-tracked,
47 * but we can't depend on this).
49 static MonoNativeTlsKey appdomain_thread_id;
51 #ifdef MONO_HAVE_FAST_TLS
53 MONO_FAST_TLS_DECLARE(tls_appdomain);
55 #define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain))
57 #define SET_APPDOMAIN(x) do { \
58 MONO_FAST_TLS_SET (tls_appdomain,x); \
59 mono_native_tls_set_value (appdomain_thread_id, x); \
60 mono_gc_set_current_thread_appdomain (x); \
63 #else /* !MONO_HAVE_FAST_TLS */
65 #define GET_APPDOMAIN() ((MonoDomain *)mono_native_tls_get_value (appdomain_thread_id))
66 #define SET_APPDOMAIN(x) do { \
67 mono_native_tls_set_value (appdomain_thread_id, x); \
68 mono_gc_set_current_thread_appdomain (x); \
73 #define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext)
74 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x))
76 static guint16 appdomain_list_size = 0;
77 static guint16 appdomain_next = 0;
78 static MonoDomain **appdomains_list = NULL;
79 static MonoImage *exe_image;
81 gboolean mono_dont_free_domains;
83 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
84 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
85 static CRITICAL_SECTION appdomains_mutex;
87 static MonoDomain *mono_root_domain = NULL;
90 static int max_domain_code_size = 0;
91 static int max_domain_code_alloc = 0;
92 static int total_domain_code_alloc = 0;
94 /* AppConfigInfo: Information about runtime versions supported by an
98 GSList *supported_runtimes;
99 char *required_runtime;
100 int configuration_count;
105 * AotModuleInfo: Contains information about AOT modules.
112 static const MonoRuntimeInfo *current_runtime = NULL;
114 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
117 * Contains information about AOT loaded code.
119 static MonoAotModuleInfoTable *aot_modules = NULL;
121 /* This is the list of runtime versions supported by this JIT.
123 static const MonoRuntimeInfo supported_runtimes[] = {
124 {"v2.0.50215","2.0", { {2,0,0,0}, {8,0,0,0}, { 3, 5, 0, 0 } } },
125 {"v2.0.50727","2.0", { {2,0,0,0}, {8,0,0,0}, { 3, 5, 0, 0 } } },
126 {"v4.0.30319","4.5", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } },
127 {"v4.0.30128","4.0", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } },
128 {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } },
129 {"moonlight", "2.1", { {2,0,5,0}, {9,0,0,0}, { 3, 5, 0, 0 } } },
133 /* The stable runtime version */
134 #define DEFAULT_RUNTIME_VERSION "v2.0.50727"
136 /* Callbacks installed by the JIT */
137 static MonoCreateDomainFunc create_domain_hook;
138 static MonoFreeDomainFunc free_domain_hook;
140 /* This is intentionally not in the header file, so people don't misuse it. */
141 extern void _mono_debug_init_corlib (MonoDomain *domain);
144 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
146 static const MonoRuntimeInfo*
147 get_runtime_by_version (const char *version);
150 mono_jit_info_find_aot_module (guint8* addr);
153 mono_domain_get_tls_key (void)
155 return appdomain_thread_id;
159 mono_domain_get_tls_offset (void)
162 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
163 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
168 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
169 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
170 #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)
172 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
173 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
175 #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
176 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
178 #define JIT_INFO_TABLE_HAZARD_INDEX 0
179 #define JIT_INFO_HAZARD_INDEX 1
182 jit_info_table_num_elements (MonoJitInfoTable *table)
185 int num_elements = 0;
187 for (i = 0; i < table->num_chunks; ++i) {
188 MonoJitInfoTableChunk *chunk = table->chunks [i];
189 int chunk_num_elements = chunk->num_elements;
192 for (j = 0; j < chunk_num_elements; ++j) {
193 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
201 static MonoJitInfoTableChunk*
202 jit_info_table_new_chunk (void)
204 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
210 static MonoJitInfoTable *
211 jit_info_table_new (MonoDomain *domain)
213 MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
215 table->domain = domain;
216 table->num_chunks = 1;
217 table->chunks [0] = jit_info_table_new_chunk ();
223 jit_info_table_free (MonoJitInfoTable *table)
226 int num_chunks = table->num_chunks;
227 MonoDomain *domain = table->domain;
229 mono_domain_lock (domain);
231 table->domain->num_jit_info_tables--;
232 if (table->domain->num_jit_info_tables <= 1) {
235 for (list = table->domain->jit_info_free_queue; list; list = list->next)
238 g_slist_free (table->domain->jit_info_free_queue);
239 table->domain->jit_info_free_queue = NULL;
242 /* At this point we assume that there are no other threads
243 still accessing the table, so we don't have to worry about
244 hazardous pointers. */
246 for (i = 0; i < num_chunks; ++i) {
247 MonoJitInfoTableChunk *chunk = table->chunks [i];
251 if (--chunk->refcount > 0)
254 num_elements = chunk->num_elements;
255 for (j = 0; j < num_elements; ++j) {
256 MonoJitInfo *ji = chunk->data [j];
258 if (IS_JIT_INFO_TOMBSTONE (ji))
265 mono_domain_unlock (domain);
270 /* The jit_info_table is sorted in ascending order by the end
271 * addresses of the compiled methods. The reason why we have to do
272 * this is that once we introduce tombstones, it becomes possible for
273 * code ranges to overlap, and if we sort by code start and insert at
274 * the back of the table, we cannot guarantee that we won't overlook
277 * There are actually two possible ways to do the sorting and
278 * inserting which work with our lock-free mechanism:
280 * 1. Sort by start address and insert at the front. When looking for
281 * an entry, find the last one with a start address lower than the one
282 * you're looking for, then work your way to the front of the table.
284 * 2. Sort by end address and insert at the back. When looking for an
285 * entry, find the first one with an end address higher than the one
286 * you're looking for, then work your way to the end of the table.
288 * We chose the latter out of convenience.
291 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
293 int left = 0, right = table->num_chunks;
295 g_assert (left < right);
298 int pos = (left + right) / 2;
299 MonoJitInfoTableChunk *chunk = table->chunks [pos];
301 if (addr < chunk->last_code_end)
305 } while (left < right);
306 g_assert (left == right);
308 if (left >= table->num_chunks)
309 return table->num_chunks - 1;
314 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
316 int left = 0, right = chunk->num_elements;
318 while (left < right) {
319 int pos = (left + right) / 2;
320 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
321 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
328 g_assert (left == right);
334 mono_jit_info_table_find (MonoDomain *domain, char *addr)
336 MonoJitInfoTable *table;
339 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
342 ++mono_stats.jit_info_table_lookup_count;
344 /* First we have to get the domain's jit_info_table. This is
345 complicated by the fact that a writer might substitute a
346 new table and free the old one. What the writer guarantees
347 us is that it looks at the hazard pointers after it has
348 changed the jit_info_table pointer. So, if we guard the
349 table by a hazard pointer and make sure that the pointer is
350 still there after we've made it hazardous, we don't have to
351 worry about the writer freeing the table. */
352 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
354 chunk_pos = jit_info_table_index (table, (gint8*)addr);
355 g_assert (chunk_pos < table->num_chunks);
357 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
359 /* We now have a position that's very close to that of the
360 first element whose end address is higher than the one
361 we're looking for. If we don't have the exact position,
362 then we have a position below that one, so we'll just
363 search upward until we find our element. */
365 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
367 while (pos < chunk->num_elements) {
368 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
372 if (IS_JIT_INFO_TOMBSTONE (ji)) {
373 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
376 if ((gint8*)addr >= (gint8*)ji->code_start
377 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
378 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
379 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
383 /* If we find a non-tombstone element which is already
384 beyond what we're looking for, we have to end the
386 if ((gint8*)addr < (gint8*)ji->code_start)
392 } while (chunk_pos < table->num_chunks);
398 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
399 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
403 /* Maybe its an AOT module */
404 image = mono_jit_info_find_aot_module ((guint8*)addr);
406 ji = jit_info_find_in_aot_func (domain, image, addr);
411 static G_GNUC_UNUSED void
412 jit_info_table_check (MonoJitInfoTable *table)
416 for (i = 0; i < table->num_chunks; ++i) {
417 MonoJitInfoTableChunk *chunk = table->chunks [i];
420 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
421 if (chunk->refcount > 10)
422 printf("warning: chunk refcount is %d\n", chunk->refcount);
423 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
425 for (j = 0; j < chunk->num_elements; ++j) {
426 MonoJitInfo *this = chunk->data [j];
429 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
431 if (j < chunk->num_elements - 1)
432 next = chunk->data [j + 1];
433 else if (i < table->num_chunks - 1) {
436 for (k = i + 1; k < table->num_chunks; ++k)
437 if (table->chunks [k]->num_elements > 0)
440 if (k >= table->num_chunks)
443 g_assert (table->chunks [k]->num_elements > 0);
444 next = table->chunks [k]->data [0];
448 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
453 static MonoJitInfoTable*
454 jit_info_table_realloc (MonoJitInfoTable *old)
457 int num_elements = jit_info_table_num_elements (old);
460 int new_chunk, new_element;
461 MonoJitInfoTable *new;
463 /* number of needed places for elements needed */
464 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
465 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
467 new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
468 new->domain = old->domain;
469 new->num_chunks = num_chunks;
471 for (i = 0; i < num_chunks; ++i)
472 new->chunks [i] = jit_info_table_new_chunk ();
476 for (i = 0; i < old->num_chunks; ++i) {
477 MonoJitInfoTableChunk *chunk = old->chunks [i];
478 int chunk_num_elements = chunk->num_elements;
481 for (j = 0; j < chunk_num_elements; ++j) {
482 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
483 g_assert (new_chunk < num_chunks);
484 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
485 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
486 new->chunks [new_chunk]->num_elements = new_element;
494 if (new_chunk < num_chunks) {
495 g_assert (new_chunk == num_chunks - 1);
496 new->chunks [new_chunk]->num_elements = new_element;
497 g_assert (new->chunks [new_chunk]->num_elements > 0);
500 for (i = 0; i < num_chunks; ++i) {
501 MonoJitInfoTableChunk *chunk = new->chunks [i];
502 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
504 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
511 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
513 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
514 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
516 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
518 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
519 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
521 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
522 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
524 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
525 + new1->data [new1->num_elements - 1]->code_size;
526 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
527 + new2->data [new2->num_elements - 1]->code_size;
533 static MonoJitInfoTable*
534 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
536 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
537 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
540 new_table->domain = table->domain;
541 new_table->num_chunks = table->num_chunks + 1;
544 for (i = 0; i < table->num_chunks; ++i) {
545 if (table->chunks [i] == chunk) {
546 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
549 new_table->chunks [j] = table->chunks [i];
550 ++new_table->chunks [j]->refcount;
555 g_assert (j == new_table->num_chunks);
560 static MonoJitInfoTableChunk*
561 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
563 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
567 for (i = 0; i < old->num_elements; ++i) {
568 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
569 new->data [j++] = old->data [i];
572 new->num_elements = j;
573 if (new->num_elements > 0)
574 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
576 new->last_code_end = old->last_code_end;
581 static MonoJitInfoTable*
582 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
584 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
585 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
588 new_table->domain = table->domain;
589 new_table->num_chunks = table->num_chunks;
592 for (i = 0; i < table->num_chunks; ++i) {
593 if (table->chunks [i] == chunk)
594 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
596 new_table->chunks [j] = table->chunks [i];
597 ++new_table->chunks [j]->refcount;
602 g_assert (j == new_table->num_chunks);
607 /* As we add an element to the table the case can arise that the chunk
608 * to which we need to add is already full. In that case we have to
609 * allocate a new table and do something about that chunk. We have
610 * several strategies:
612 * If the number of elements in the table is below the low watermark
613 * or above the high watermark, we reallocate the whole table.
614 * Otherwise we only concern ourselves with the overflowing chunk:
616 * If there are no tombstones in the chunk then we split the chunk in
617 * two, each half full.
619 * If the chunk does contain tombstones, we just make a new copy of
620 * the chunk without the tombstones, which will have room for at least
621 * the one element we have to add.
623 static MonoJitInfoTable*
624 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
626 int num_elements = jit_info_table_num_elements (table);
629 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
630 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
631 //printf ("reallocing table\n");
632 return jit_info_table_realloc (table);
635 /* count the number of non-tombstone elements in the chunk */
637 for (i = 0; i < chunk->num_elements; ++i) {
638 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
642 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
643 //printf ("splitting chunk\n");
644 return jit_info_table_copy_and_split_chunk (table, chunk);
647 //printf ("purifying chunk\n");
648 return jit_info_table_copy_and_purify_chunk (table, chunk);
651 /* We add elements to the table by first making space for them by
652 * shifting the elements at the back to the right, one at a time.
653 * This results in duplicate entries during the process, but during
654 * all the time the table is in a sorted state. Also, when an element
655 * is replaced by another one, the element that replaces it has an end
656 * address that is equal to or lower than that of the replaced
657 * element. That property is necessary to guarantee that when
658 * searching for an element we end up at a position not higher than
659 * the one we're looking for (i.e. we either find the element directly
660 * or we end up to the left of it).
663 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
665 MonoJitInfoTable *table;
667 MonoJitInfoTableChunk *chunk;
671 g_assert (ji->method != NULL);
673 mono_domain_lock (domain);
675 ++mono_stats.jit_info_table_insert_count;
677 table = domain->jit_info_table;
680 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
681 g_assert (chunk_pos < table->num_chunks);
682 chunk = table->chunks [chunk_pos];
684 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
685 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
687 /* Debugging code, should be removed. */
688 //jit_info_table_check (new_table);
690 domain->jit_info_table = new_table;
691 mono_memory_barrier ();
692 domain->num_jit_info_tables++;
693 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free);
699 /* Debugging code, should be removed. */
700 //jit_info_table_check (table);
702 num_elements = chunk->num_elements;
704 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
706 /* First we need to size up the chunk by one, by copying the
707 last item, or inserting the first one, if the table is
709 if (num_elements > 0)
710 chunk->data [num_elements] = chunk->data [num_elements - 1];
712 chunk->data [0] = ji;
713 mono_memory_write_barrier ();
714 chunk->num_elements = ++num_elements;
716 /* Shift the elements up one by one. */
717 for (i = num_elements - 2; i >= pos; --i) {
718 mono_memory_write_barrier ();
719 chunk->data [i + 1] = chunk->data [i];
722 /* Now we have room and can insert the new item. */
723 mono_memory_write_barrier ();
724 chunk->data [pos] = ji;
726 /* Set the high code end address chunk entry. */
727 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
728 + chunk->data [chunk->num_elements - 1]->code_size;
730 /* Debugging code, should be removed. */
731 //jit_info_table_check (table);
733 mono_domain_unlock (domain);
737 mono_jit_info_make_tombstone (MonoJitInfo *ji)
739 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
741 tombstone->code_start = ji->code_start;
742 tombstone->code_size = ji->code_size;
743 tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
749 * LOCKING: domain lock
752 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
754 if (domain->num_jit_info_tables <= 1) {
755 /* Can it actually happen that we only have one table
756 but ji is still hazardous? */
757 mono_thread_hazardous_free_or_queue (ji, g_free);
759 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
764 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
766 MonoJitInfoTable *table;
767 MonoJitInfoTableChunk *chunk;
768 gpointer start = ji->code_start;
771 mono_domain_lock (domain);
772 table = domain->jit_info_table;
774 ++mono_stats.jit_info_table_remove_count;
776 chunk_pos = jit_info_table_index (table, start);
777 g_assert (chunk_pos < table->num_chunks);
779 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
782 chunk = table->chunks [chunk_pos];
784 while (pos < chunk->num_elements) {
785 if (chunk->data [pos] == ji)
788 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
789 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
790 <= (guint8*)ji->code_start + ji->code_size);
797 } while (chunk_pos < table->num_chunks);
800 g_assert (chunk->data [pos] == ji);
802 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
804 /* Debugging code, should be removed. */
805 //jit_info_table_check (table);
807 mono_jit_info_free_or_queue (domain, ji);
809 mono_domain_unlock (domain);
812 static MonoAotModuleInfoTable*
813 mono_aot_module_info_table_new (void)
815 return g_array_new (FALSE, FALSE, sizeof (gpointer));
819 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
821 int left = 0, right = table->len;
823 while (left < right) {
824 int pos = (left + right) / 2;
825 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
826 char *start = ainfo->start;
827 char *end = ainfo->end;
831 else if (addr >= end)
841 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
843 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
846 ainfo->image = image;
847 ainfo->start = start;
850 mono_appdomains_lock ();
853 aot_modules = mono_aot_module_info_table_new ();
855 pos = aot_info_table_index (aot_modules, start);
857 g_array_insert_val (aot_modules, pos, ainfo);
859 mono_appdomains_unlock ();
863 mono_jit_info_find_aot_module (guint8* addr)
865 guint left = 0, right;
870 mono_appdomains_lock ();
872 right = aot_modules->len;
873 while (left < right) {
874 guint pos = (left + right) / 2;
875 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
877 if (addr < (guint8*)ai->start)
879 else if (addr >= (guint8*)ai->end)
882 mono_appdomains_unlock ();
887 mono_appdomains_unlock ();
893 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
895 jit_info_find_in_aot_func = func;
899 mono_jit_info_get_code_start (MonoJitInfo* ji)
901 return ji->code_start;
905 mono_jit_info_get_code_size (MonoJitInfo* ji)
907 return ji->code_size;
911 mono_jit_info_get_method (MonoJitInfo* ji)
917 jit_info_key_extract (gpointer value)
919 MonoJitInfo *info = (MonoJitInfo*)value;
925 jit_info_next_value (gpointer value)
927 MonoJitInfo *info = (MonoJitInfo*)value;
929 return (gpointer*)&info->next_jit_code_hash;
933 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
935 mono_internal_hash_table_init (jit_code_hash,
936 mono_aligned_addr_hash,
937 jit_info_key_extract,
938 jit_info_next_value);
942 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
944 if (ji->has_generic_jit_info)
945 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
951 * mono_jit_info_get_generic_sharing_context:
954 * Returns the jit info's generic sharing context, or NULL if it
957 MonoGenericSharingContext*
958 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
960 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
963 return gi->generic_sharing_context;
969 * mono_jit_info_set_generic_sharing_context:
971 * @gsctx: a generic sharing context
973 * Sets the jit info's generic sharing context. The jit info must
974 * have memory allocated for the context.
977 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
979 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
983 gi->generic_sharing_context = gsctx;
986 MonoTryBlockHoleTableJitInfo*
987 mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
989 if (ji->has_try_block_holes) {
990 char *ptr = (char*)&ji->clauses [ji->num_clauses];
991 if (ji->has_generic_jit_info)
992 ptr += sizeof (MonoGenericJitInfo);
993 return (MonoTryBlockHoleTableJitInfo*)ptr;
1000 mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
1002 if (ji->has_arch_eh_info) {
1003 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1004 if (ji->has_generic_jit_info)
1005 ptr += sizeof (MonoGenericJitInfo);
1006 if (ji->has_try_block_holes)
1007 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
1008 return (MonoArchEHJitInfo*)ptr;
1015 mono_jit_info_get_cas_info (MonoJitInfo *ji)
1017 if (ji->has_cas_info) {
1018 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1019 if (ji->has_generic_jit_info)
1020 ptr += sizeof (MonoGenericJitInfo);
1021 if (ji->has_try_block_holes)
1022 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
1023 if (ji->has_arch_eh_info)
1024 ptr += sizeof (MonoArchEHJitInfo);
1025 return (MonoMethodCasInfo*)ptr;
1032 mono_install_create_domain_hook (MonoCreateDomainFunc func)
1034 create_domain_hook = func;
1038 mono_install_free_domain_hook (MonoFreeDomainFunc func)
1040 free_domain_hook = func;
1044 * mono_string_equal:
1045 * @s1: First string to compare
1046 * @s2: Second string to compare
1048 * Returns FALSE if the strings differ.
1051 mono_string_equal (MonoString *s1, MonoString *s2)
1053 int l1 = mono_string_length (s1);
1054 int l2 = mono_string_length (s2);
1061 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
1066 * @s: the string to hash
1068 * Returns the hash for the string.
1071 mono_string_hash (MonoString *s)
1073 const guint16 *p = mono_string_chars (s);
1074 int i, len = mono_string_length (s);
1077 for (i = 0; i < len; i++) {
1078 h = (h << 5) - h + *p;
1086 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1088 int len = GPOINTER_TO_INT (s1 [0]);
1089 if (len != GPOINTER_TO_INT (s2 [0]))
1092 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1096 mono_ptrarray_hash (gpointer *s)
1099 int len = GPOINTER_TO_INT (s [0]);
1102 for (i = 1; i < len; i++)
1103 hash += GPOINTER_TO_UINT (s [i]);
1109 * Allocate an id for domain and set domain->domain_id.
1110 * LOCKING: must be called while holding appdomains_mutex.
1111 * We try to assign low numbers to the domain, so it can be used
1112 * as an index in data tables to lookup domain-specific info
1113 * with minimal memory overhead. We also try not to reuse the
1114 * same id too quickly (to help debugging).
1117 domain_id_alloc (MonoDomain *domain)
1120 if (!appdomains_list) {
1121 appdomain_list_size = 2;
1122 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1124 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1125 if (!appdomains_list [i]) {
1131 for (i = 0; i < appdomain_next; ++i) {
1132 if (!appdomains_list [i]) {
1139 MonoDomain **new_list;
1140 int new_size = appdomain_list_size * 2;
1141 if (new_size >= (1 << 16))
1142 g_assert_not_reached ();
1143 id = appdomain_list_size;
1144 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1145 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1146 mono_gc_free_fixed (appdomains_list);
1147 appdomains_list = new_list;
1148 appdomain_list_size = new_size;
1150 domain->domain_id = id;
1151 appdomains_list [id] = domain;
1153 if (appdomain_next > appdomain_list_size)
1158 static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1159 static gpointer domain_gc_desc = NULL;
1160 static guint32 domain_shadow_serial = 0L;
1163 mono_domain_create (void)
1166 guint32 shadow_serial;
1168 mono_appdomains_lock ();
1169 shadow_serial = domain_shadow_serial++;
1171 if (!domain_gc_desc) {
1172 unsigned int i, bit = 0;
1173 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1174 bit = i / sizeof (gpointer);
1175 domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32);
1177 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1179 mono_appdomains_unlock ();
1181 #ifdef HAVE_BOEHM_GC
1183 * Boehm doesn't like roots inside GC allocated objects, and alloc_fixed returns
1184 * a GC_MALLOC-ed object, contrary to the api docs. This causes random crashes when
1185 * running the corlib test suite.
1186 * To solve this, we pass a NULL descriptor, and don't register roots.
1188 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL);
1190 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1191 mono_gc_register_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED), G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_LAST_GC_TRACKED) - G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED), NULL);
1193 domain->shadow_serial = shadow_serial;
1194 domain->domain = NULL;
1195 domain->setup = NULL;
1196 domain->friendly_name = NULL;
1197 domain->search_path = NULL;
1199 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1201 domain->mp = mono_mempool_new ();
1202 domain->code_mp = mono_code_manager_new ();
1203 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1204 domain->domain_assemblies = NULL;
1205 domain->assembly_bindings = NULL;
1206 domain->assembly_bindings_parsed = FALSE;
1207 domain->class_vtable_array = g_ptr_array_new ();
1208 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1209 domain->static_data_array = NULL;
1210 mono_jit_code_hash_init (&domain->jit_code_hash);
1211 domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1212 domain->num_jit_info_tables = 1;
1213 domain->jit_info_table = jit_info_table_new (domain);
1214 domain->jit_info_free_queue = NULL;
1215 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1216 domain->track_resurrection_handles_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1217 domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1219 InitializeCriticalSection (&domain->lock);
1220 InitializeCriticalSection (&domain->assemblies_lock);
1221 InitializeCriticalSection (&domain->jit_code_hash_lock);
1222 InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
1224 domain->method_rgctx_hash = NULL;
1226 mono_appdomains_lock ();
1227 domain_id_alloc (domain);
1228 mono_appdomains_unlock ();
1230 #ifndef DISABLE_PERFCOUNTERS
1231 mono_perfcounters->loader_appdomains++;
1232 mono_perfcounters->loader_total_appdomains++;
1235 mono_debug_domain_create (domain);
1237 if (create_domain_hook)
1238 create_domain_hook (domain);
1240 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1246 * mono_init_internal:
1248 * Creates the initial application domain and initializes the mono_defaults
1250 * This function is guaranteed to not run any IL code.
1251 * If exe_filename is not NULL, the method will determine the required runtime
1252 * from the exe configuration file or the version PE field.
1253 * If runtime_version is not NULL, that runtime version will be used.
1254 * Either exe_filename or runtime_version must be provided.
1256 * Returns: the initial domain.
1259 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1261 static MonoDomain *domain = NULL;
1262 MonoAssembly *ass = NULL;
1263 MonoImageOpenStatus status = MONO_IMAGE_OK;
1264 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1268 g_assert_not_reached ();
1271 /* Avoid system error message boxes. */
1272 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1279 #ifndef DISABLE_PERFCOUNTERS
1280 mono_perfcounters_init ();
1283 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1284 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1285 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1287 mono_gc_base_init ();
1289 MONO_FAST_TLS_INIT (tls_appdomain);
1290 mono_native_tls_alloc (&appdomain_thread_id, NULL);
1292 InitializeCriticalSection (&appdomains_mutex);
1294 mono_metadata_init ();
1295 mono_images_init ();
1296 mono_assemblies_init ();
1297 mono_classes_init ();
1298 mono_loader_init ();
1299 mono_reflection_init ();
1301 /* FIXME: When should we release this memory? */
1302 MONO_GC_REGISTER_ROOT_FIXED (appdomains_list);
1304 domain = mono_domain_create ();
1305 mono_root_domain = domain;
1307 SET_APPDOMAIN (domain);
1309 /* Get a list of runtimes supported by the exe */
1310 if (exe_filename != NULL) {
1312 * This function will load the exe file as a MonoImage. We need to close it, but
1313 * that would mean it would be reloaded later. So instead, we save it to
1314 * exe_image, and close it during shutdown.
1316 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1319 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1321 exe_image = mono_image_open (exe_filename, NULL);
1323 mono_fixup_exe_image (exe_image);
1325 } else if (runtime_version != NULL) {
1326 runtimes [0] = get_runtime_by_version (runtime_version);
1327 runtimes [1] = NULL;
1330 if (runtimes [0] == NULL) {
1331 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1332 runtimes [0] = default_runtime;
1333 runtimes [1] = NULL;
1334 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1335 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1338 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1339 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1340 current_runtime = runtimes [n];
1341 ass = mono_assembly_load_corlib (current_runtime, &status);
1342 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1347 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1349 case MONO_IMAGE_ERROR_ERRNO: {
1350 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1351 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1352 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1353 g_free (corlib_file);
1356 case MONO_IMAGE_IMAGE_INVALID:
1357 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1358 mono_assembly_getrootdir ());
1360 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1361 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1362 mono_assembly_getrootdir ());
1365 /* to suppress compiler warning */
1371 mono_defaults.corlib = mono_assembly_get_image (ass);
1373 mono_defaults.object_class = mono_class_from_name (
1374 mono_defaults.corlib, "System", "Object");
1375 g_assert (mono_defaults.object_class != 0);
1377 mono_defaults.void_class = mono_class_from_name (
1378 mono_defaults.corlib, "System", "Void");
1379 g_assert (mono_defaults.void_class != 0);
1381 mono_defaults.boolean_class = mono_class_from_name (
1382 mono_defaults.corlib, "System", "Boolean");
1383 g_assert (mono_defaults.boolean_class != 0);
1385 mono_defaults.byte_class = mono_class_from_name (
1386 mono_defaults.corlib, "System", "Byte");
1387 g_assert (mono_defaults.byte_class != 0);
1389 mono_defaults.sbyte_class = mono_class_from_name (
1390 mono_defaults.corlib, "System", "SByte");
1391 g_assert (mono_defaults.sbyte_class != 0);
1393 mono_defaults.int16_class = mono_class_from_name (
1394 mono_defaults.corlib, "System", "Int16");
1395 g_assert (mono_defaults.int16_class != 0);
1397 mono_defaults.uint16_class = mono_class_from_name (
1398 mono_defaults.corlib, "System", "UInt16");
1399 g_assert (mono_defaults.uint16_class != 0);
1401 mono_defaults.int32_class = mono_class_from_name (
1402 mono_defaults.corlib, "System", "Int32");
1403 g_assert (mono_defaults.int32_class != 0);
1405 mono_defaults.uint32_class = mono_class_from_name (
1406 mono_defaults.corlib, "System", "UInt32");
1407 g_assert (mono_defaults.uint32_class != 0);
1409 mono_defaults.uint_class = mono_class_from_name (
1410 mono_defaults.corlib, "System", "UIntPtr");
1411 g_assert (mono_defaults.uint_class != 0);
1413 mono_defaults.int_class = mono_class_from_name (
1414 mono_defaults.corlib, "System", "IntPtr");
1415 g_assert (mono_defaults.int_class != 0);
1417 mono_defaults.int64_class = mono_class_from_name (
1418 mono_defaults.corlib, "System", "Int64");
1419 g_assert (mono_defaults.int64_class != 0);
1421 mono_defaults.uint64_class = mono_class_from_name (
1422 mono_defaults.corlib, "System", "UInt64");
1423 g_assert (mono_defaults.uint64_class != 0);
1425 mono_defaults.single_class = mono_class_from_name (
1426 mono_defaults.corlib, "System", "Single");
1427 g_assert (mono_defaults.single_class != 0);
1429 mono_defaults.double_class = mono_class_from_name (
1430 mono_defaults.corlib, "System", "Double");
1431 g_assert (mono_defaults.double_class != 0);
1433 mono_defaults.char_class = mono_class_from_name (
1434 mono_defaults.corlib, "System", "Char");
1435 g_assert (mono_defaults.char_class != 0);
1437 mono_defaults.string_class = mono_class_from_name (
1438 mono_defaults.corlib, "System", "String");
1439 g_assert (mono_defaults.string_class != 0);
1441 mono_defaults.enum_class = mono_class_from_name (
1442 mono_defaults.corlib, "System", "Enum");
1443 g_assert (mono_defaults.enum_class != 0);
1445 mono_defaults.array_class = mono_class_from_name (
1446 mono_defaults.corlib, "System", "Array");
1447 g_assert (mono_defaults.array_class != 0);
1449 mono_defaults.delegate_class = mono_class_from_name (
1450 mono_defaults.corlib, "System", "Delegate");
1451 g_assert (mono_defaults.delegate_class != 0 );
1453 mono_defaults.multicastdelegate_class = mono_class_from_name (
1454 mono_defaults.corlib, "System", "MulticastDelegate");
1455 g_assert (mono_defaults.multicastdelegate_class != 0 );
1457 mono_defaults.asyncresult_class = mono_class_from_name (
1458 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1460 g_assert (mono_defaults.asyncresult_class != 0 );
1462 mono_defaults.manualresetevent_class = mono_class_from_name (
1463 mono_defaults.corlib, "System.Threading", "ManualResetEvent");
1464 g_assert (mono_defaults.manualresetevent_class != 0 );
1466 mono_defaults.typehandle_class = mono_class_from_name (
1467 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1468 g_assert (mono_defaults.typehandle_class != 0);
1470 mono_defaults.methodhandle_class = mono_class_from_name (
1471 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1472 g_assert (mono_defaults.methodhandle_class != 0);
1474 mono_defaults.fieldhandle_class = mono_class_from_name (
1475 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1476 g_assert (mono_defaults.fieldhandle_class != 0);
1478 mono_defaults.systemtype_class = mono_class_from_name (
1479 mono_defaults.corlib, "System", "Type");
1480 g_assert (mono_defaults.systemtype_class != 0);
1482 mono_defaults.monotype_class = mono_class_from_name (
1483 mono_defaults.corlib, "System", "MonoType");
1484 g_assert (mono_defaults.monotype_class != 0);
1486 mono_defaults.exception_class = mono_class_from_name (
1487 mono_defaults.corlib, "System", "Exception");
1488 g_assert (mono_defaults.exception_class != 0);
1490 mono_defaults.threadabortexception_class = mono_class_from_name (
1491 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1492 g_assert (mono_defaults.threadabortexception_class != 0);
1494 mono_defaults.thread_class = mono_class_from_name (
1495 mono_defaults.corlib, "System.Threading", "Thread");
1496 g_assert (mono_defaults.thread_class != 0);
1498 mono_defaults.internal_thread_class = mono_class_from_name (
1499 mono_defaults.corlib, "System.Threading", "InternalThread");
1500 if (!mono_defaults.internal_thread_class) {
1501 /* This can happen with an old mscorlib */
1502 fprintf (stderr, "Corlib too old for this runtime.\n");
1503 fprintf (stderr, "Loaded from: %s\n",
1504 mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown");
1508 mono_defaults.appdomain_class = mono_class_from_name (
1509 mono_defaults.corlib, "System", "AppDomain");
1510 g_assert (mono_defaults.appdomain_class != 0);
1512 mono_defaults.transparent_proxy_class = mono_class_from_name (
1513 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1514 g_assert (mono_defaults.transparent_proxy_class != 0);
1516 mono_defaults.real_proxy_class = mono_class_from_name (
1517 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1518 g_assert (mono_defaults.real_proxy_class != 0);
1520 mono_defaults.mono_method_message_class = mono_class_from_name (
1521 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1522 g_assert (mono_defaults.mono_method_message_class != 0);
1524 mono_defaults.field_info_class = mono_class_from_name (
1525 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1526 g_assert (mono_defaults.field_info_class != 0);
1528 mono_defaults.method_info_class = mono_class_from_name (
1529 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1530 g_assert (mono_defaults.method_info_class != 0);
1532 mono_defaults.stringbuilder_class = mono_class_from_name (
1533 mono_defaults.corlib, "System.Text", "StringBuilder");
1534 g_assert (mono_defaults.stringbuilder_class != 0);
1536 mono_defaults.math_class = mono_class_from_name (
1537 mono_defaults.corlib, "System", "Math");
1538 g_assert (mono_defaults.math_class != 0);
1540 mono_defaults.stack_frame_class = mono_class_from_name (
1541 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1542 g_assert (mono_defaults.stack_frame_class != 0);
1544 mono_defaults.stack_trace_class = mono_class_from_name (
1545 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1546 g_assert (mono_defaults.stack_trace_class != 0);
1548 mono_defaults.marshal_class = mono_class_from_name (
1549 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1550 g_assert (mono_defaults.marshal_class != 0);
1552 mono_defaults.iserializeable_class = mono_class_from_name (
1553 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1554 g_assert (mono_defaults.iserializeable_class != 0);
1556 mono_defaults.serializationinfo_class = mono_class_from_name (
1557 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1558 g_assert (mono_defaults.serializationinfo_class != 0);
1560 mono_defaults.streamingcontext_class = mono_class_from_name (
1561 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1562 g_assert (mono_defaults.streamingcontext_class != 0);
1564 mono_defaults.typed_reference_class = mono_class_from_name (
1565 mono_defaults.corlib, "System", "TypedReference");
1566 g_assert (mono_defaults.typed_reference_class != 0);
1568 mono_defaults.argumenthandle_class = mono_class_from_name (
1569 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1570 g_assert (mono_defaults.argumenthandle_class != 0);
1572 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1573 mono_defaults.corlib, "System", "MarshalByRefObject");
1574 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1576 mono_defaults.monitor_class = mono_class_from_name (
1577 mono_defaults.corlib, "System.Threading", "Monitor");
1578 g_assert (mono_defaults.monitor_class != 0);
1580 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1581 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1582 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1584 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1585 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1587 mono_defaults.executioncontext_class = mono_class_from_name (
1588 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1590 mono_defaults.internals_visible_class = mono_class_from_name (
1591 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1593 mono_defaults.critical_finalizer_object = mono_class_from_name (
1594 mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
1597 * mscorlib needs a little help, only now it can load its friends list (after we have
1598 * loaded the InternalsVisibleToAttribute), load it now
1600 mono_assembly_load_friends (ass);
1602 mono_defaults.safehandle_class = mono_class_from_name (
1603 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1605 mono_defaults.handleref_class = mono_class_from_name (
1606 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1608 mono_defaults.attribute_class = mono_class_from_name (
1609 mono_defaults.corlib, "System", "Attribute");
1611 mono_defaults.customattribute_data_class = mono_class_from_name (
1612 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1614 /* these are initialized lazily when COM features are used */
1616 mono_defaults.variant_class = NULL;
1617 mono_defaults.com_object_class = NULL;
1618 mono_defaults.com_interop_proxy_class = NULL;
1619 mono_defaults.iunknown_class = NULL;
1620 mono_defaults.idispatch_class = NULL;
1624 * Note that mono_defaults.generic_*_class is only non-NULL if we're
1625 * using the 2.0 corlib.
1627 mono_class_init (mono_defaults.array_class);
1628 mono_defaults.generic_nullable_class = mono_class_from_name (
1629 mono_defaults.corlib, "System", "Nullable`1");
1630 mono_defaults.generic_ilist_class = mono_class_from_name (
1631 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1633 domain->friendly_name = g_path_get_basename (filename);
1635 _mono_debug_init_corlib (domain);
1643 * Creates the initial application domain and initializes the mono_defaults
1645 * This function is guaranteed to not run any IL code.
1646 * The runtime is initialized using the default runtime version.
1648 * Returns: the initial domain.
1651 mono_init (const char *domain_name)
1653 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1657 * mono_init_from_assembly:
1658 * @domain_name: name to give to the initial domain
1659 * @filename: filename to load on startup
1661 * Used by the runtime, users should use mono_jit_init instead.
1663 * Creates the initial application domain and initializes the mono_defaults
1665 * This function is guaranteed to not run any IL code.
1666 * The runtime is initialized using the runtime version required by the
1667 * provided executable. The version is determined by looking at the exe
1668 * configuration file and the version PE field)
1670 * Returns: the initial domain.
1673 mono_init_from_assembly (const char *domain_name, const char *filename)
1675 return mono_init_internal (domain_name, filename, NULL);
1679 * mono_init_version:
1681 * Used by the runtime, users should use mono_jit_init instead.
1683 * Creates the initial application domain and initializes the mono_defaults
1686 * This function is guaranteed to not run any IL code.
1687 * The runtime is initialized using the provided rutime version.
1689 * Returns: the initial domain.
1692 mono_init_version (const char *domain_name, const char *version)
1694 return mono_init_internal (domain_name, NULL, version);
1699 * mono_init_com_types:
1701 * Initializes all types needed for COM Interop in mono_defaults structure.
1704 mono_init_com_types (void)
1706 static gboolean initialized = FALSE;
1711 /* FIXME: do I need some threading protection here */
1713 g_assert (mono_defaults.corlib);
1715 mono_defaults.variant_class = mono_class_from_name (
1716 mono_defaults.corlib, "System", "Variant");
1717 g_assert (mono_defaults.variant_class != 0);
1719 mono_defaults.com_object_class = mono_class_from_name (
1720 mono_defaults.corlib, "System", "__ComObject");
1721 g_assert (mono_defaults.com_object_class != 0);
1723 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1724 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1725 g_assert (mono_defaults.com_interop_proxy_class != 0);
1727 mono_defaults.iunknown_class = mono_class_from_name (
1728 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1729 g_assert (mono_defaults.iunknown_class != 0);
1731 mono_defaults.idispatch_class = mono_class_from_name (
1732 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1733 g_assert (mono_defaults.idispatch_class != 0);
1737 #endif /*DISABLE_COM*/
1742 * Cleans up all metadata modules.
1747 mono_close_exe_image ();
1749 mono_defaults.corlib = NULL;
1751 mono_config_cleanup ();
1752 mono_loader_cleanup ();
1753 mono_classes_cleanup ();
1754 mono_assemblies_cleanup ();
1755 mono_images_cleanup ();
1756 mono_debug_cleanup ();
1757 mono_metadata_cleanup ();
1759 mono_native_tls_free (appdomain_thread_id);
1760 DeleteCriticalSection (&appdomains_mutex);
1768 mono_close_exe_image (void)
1771 mono_image_close (exe_image);
1775 * mono_get_root_domain:
1777 * The root AppDomain is the initial domain created by the runtime when it is
1778 * initialized. Programs execute on this AppDomain, but can create new ones
1779 * later. Currently there is no unmanaged API to create new AppDomains, this
1780 * must be done from managed code.
1782 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1785 mono_get_root_domain (void)
1787 return mono_root_domain;
1793 * Returns: the current domain, to obtain the root domain use
1794 * mono_get_root_domain().
1799 return GET_APPDOMAIN ();
1803 mono_domain_unset (void)
1805 SET_APPDOMAIN (NULL);
1809 mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception)
1811 MonoInternalThread *thread;
1813 if (mono_domain_get () == domain)
1816 SET_APPDOMAIN (domain);
1817 SET_APPCONTEXT (domain->default_context);
1819 if (migrate_exception) {
1820 thread = mono_thread_internal_current ();
1821 if (!thread->abort_exc)
1824 g_assert (thread->abort_exc->object.vtable->domain != domain);
1825 MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
1826 g_assert (thread->abort_exc->object.vtable->domain == domain);
1831 * mono_domain_set_internal:
1832 * @domain: the new domain
1834 * Sets the current domain to @domain.
1837 mono_domain_set_internal (MonoDomain *domain)
1839 mono_domain_set_internal_with_options (domain, TRUE);
1843 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1849 * Create a copy of the data to avoid calling the user callback
1850 * inside the lock because that could lead to deadlocks.
1851 * We can do this because this function is not perf. critical.
1853 mono_appdomains_lock ();
1854 size = appdomain_list_size;
1855 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1856 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1857 mono_appdomains_unlock ();
1859 for (i = 0; i < size; ++i) {
1861 func (copy [i], user_data);
1864 mono_gc_free_fixed (copy);
1868 * mono_domain_assembly_open:
1869 * @domain: the application domain
1870 * @name: file name of the assembly
1872 * fixme: maybe we should integrate this with mono_assembly_open ??
1875 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1877 MonoDomain *current;
1881 mono_domain_assemblies_lock (domain);
1882 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1884 if (strcmp (name, ass->aname.name) == 0) {
1885 mono_domain_assemblies_unlock (domain);
1889 mono_domain_assemblies_unlock (domain);
1891 if (domain != mono_domain_get ()) {
1892 current = mono_domain_get ();
1894 mono_domain_set (domain, FALSE);
1895 ass = mono_assembly_open (name, NULL);
1896 mono_domain_set (current, FALSE);
1898 ass = mono_assembly_open (name, NULL);
1905 free_slist (gpointer key, gpointer value, gpointer user_data)
1907 g_slist_free (value);
1911 unregister_vtable_reflection_type (MonoVTable *vtable)
1913 MonoObject *type = vtable->type;
1915 if (type->vtable->klass != mono_defaults.monotype_class)
1916 MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type);
1920 mono_domain_free (MonoDomain *domain, gboolean force)
1922 int code_size, code_alloc;
1924 if ((domain == mono_root_domain) && !force) {
1925 g_warning ("cant unload root domain");
1929 if (mono_dont_free_domains)
1932 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1934 mono_debug_domain_unload (domain);
1936 mono_appdomains_lock ();
1937 appdomains_list [domain->domain_id] = NULL;
1938 mono_appdomains_unlock ();
1940 /* must do this early as it accesses fields and types */
1941 if (domain->special_static_fields) {
1942 mono_alloc_special_static_data_free (domain->special_static_fields);
1943 g_hash_table_destroy (domain->special_static_fields);
1944 domain->special_static_fields = NULL;
1948 * We must destroy all these hash tables here because they
1949 * contain references to managed objects belonging to the
1950 * domain. Once we let the GC clear the domain there must be
1951 * no more such references, or we'll crash if a collection
1954 mono_g_hash_table_destroy (domain->ldstr_table);
1955 domain->ldstr_table = NULL;
1957 mono_g_hash_table_destroy (domain->env);
1960 if (domain->tlsrec_list) {
1961 mono_thread_destroy_domain_tls (domain);
1962 domain->tlsrec_list = NULL;
1965 mono_reflection_cleanup_domain (domain);
1967 if (domain->type_hash) {
1968 mono_g_hash_table_destroy (domain->type_hash);
1969 domain->type_hash = NULL;
1971 if (domain->type_init_exception_hash) {
1972 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1973 domain->type_init_exception_hash = NULL;
1976 if (domain->class_vtable_array) {
1978 for (i = 0; i < domain->class_vtable_array->len; ++i)
1979 unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i));
1982 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1983 MonoAssembly *ass = tmp->data;
1984 mono_assembly_release_gc_roots (ass);
1987 /* This needs to be done before closing assemblies */
1988 mono_gc_clear_domain (domain);
1990 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1991 MonoAssembly *ass = tmp->data;
1992 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s[%p], assembly %s[%p], ref_count=%d", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count);
1993 if (!mono_assembly_close_except_image_pools (ass))
1997 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1998 MonoAssembly *ass = tmp->data;
2000 mono_assembly_close_finish (ass);
2002 g_slist_free (domain->domain_assemblies);
2003 domain->domain_assemblies = NULL;
2006 * Send this after the assemblies have been unloaded and the domain is still in a
2009 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
2011 if (free_domain_hook)
2012 free_domain_hook (domain);
2014 /* FIXME: free delegate_hash_table when it's used */
2015 if (domain->search_path) {
2016 g_strfreev (domain->search_path);
2017 domain->search_path = NULL;
2019 domain->create_proxy_for_type_method = NULL;
2020 domain->private_invoke_method = NULL;
2021 domain->default_context = NULL;
2022 domain->out_of_memory_ex = NULL;
2023 domain->null_reference_ex = NULL;
2024 domain->stack_overflow_ex = NULL;
2025 domain->ephemeron_tombstone = NULL;
2026 domain->entry_assembly = NULL;
2028 g_free (domain->friendly_name);
2029 domain->friendly_name = NULL;
2030 g_ptr_array_free (domain->class_vtable_array, TRUE);
2031 domain->class_vtable_array = NULL;
2032 g_hash_table_destroy (domain->proxy_vtable_hash);
2033 domain->proxy_vtable_hash = NULL;
2034 if (domain->static_data_array) {
2035 mono_gc_free_fixed (domain->static_data_array);
2036 domain->static_data_array = NULL;
2038 mono_internal_hash_table_destroy (&domain->jit_code_hash);
2041 * There might still be jit info tables of this domain which
2042 * are not freed. Since the domain cannot be in use anymore,
2043 * this will free them.
2045 mono_thread_hazardous_try_free_all ();
2046 g_assert (domain->num_jit_info_tables == 1);
2047 jit_info_table_free (domain->jit_info_table);
2048 domain->jit_info_table = NULL;
2049 g_assert (!domain->jit_info_free_queue);
2051 /* collect statistics */
2052 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
2053 total_domain_code_alloc += code_alloc;
2054 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
2055 max_domain_code_size = MAX (max_domain_code_size, code_size);
2057 #ifdef DEBUG_DOMAIN_UNLOAD
2058 mono_mempool_invalidate (domain->mp);
2059 mono_code_manager_invalidate (domain->code_mp);
2061 #ifndef DISABLE_PERFCOUNTERS
2062 mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
2064 mono_mempool_destroy (domain->mp);
2066 mono_code_manager_destroy (domain->code_mp);
2067 domain->code_mp = NULL;
2070 g_hash_table_destroy (domain->finalizable_objects_hash);
2071 domain->finalizable_objects_hash = NULL;
2072 if (domain->track_resurrection_objects_hash) {
2073 g_hash_table_foreach (domain->track_resurrection_objects_hash, free_slist, NULL);
2074 g_hash_table_destroy (domain->track_resurrection_objects_hash);
2076 if (domain->track_resurrection_handles_hash)
2077 g_hash_table_destroy (domain->track_resurrection_handles_hash);
2078 if (domain->method_rgctx_hash) {
2079 g_hash_table_destroy (domain->method_rgctx_hash);
2080 domain->method_rgctx_hash = NULL;
2082 if (domain->generic_virtual_cases) {
2083 g_hash_table_destroy (domain->generic_virtual_cases);
2084 domain->generic_virtual_cases = NULL;
2086 if (domain->generic_virtual_thunks) {
2087 g_hash_table_destroy (domain->generic_virtual_thunks);
2088 domain->generic_virtual_thunks = NULL;
2090 if (domain->ftnptrs_hash) {
2091 g_hash_table_destroy (domain->ftnptrs_hash);
2092 domain->ftnptrs_hash = NULL;
2095 DeleteCriticalSection (&domain->finalizable_objects_hash_lock);
2096 DeleteCriticalSection (&domain->assemblies_lock);
2097 DeleteCriticalSection (&domain->jit_code_hash_lock);
2098 DeleteCriticalSection (&domain->lock);
2099 domain->setup = NULL;
2101 mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
2103 /* FIXME: anything else required ? */
2105 mono_gc_free_fixed (domain);
2107 #ifndef DISABLE_PERFCOUNTERS
2108 mono_perfcounters->loader_appdomains--;
2111 if (domain == mono_root_domain)
2112 mono_root_domain = NULL;
2116 * mono_domain_get_id:
2119 * Returns: the a domain for a specific domain id.
2122 mono_domain_get_by_id (gint32 domainid)
2124 MonoDomain * domain;
2126 mono_appdomains_lock ();
2127 if (domainid < appdomain_list_size)
2128 domain = appdomains_list [domainid];
2131 mono_appdomains_unlock ();
2137 mono_domain_get_id (MonoDomain *domain)
2139 return domain->domain_id;
2143 * mono_domain_alloc:
2145 * LOCKING: Acquires the domain lock.
2148 mono_domain_alloc (MonoDomain *domain, guint size)
2152 mono_domain_lock (domain);
2153 #ifndef DISABLE_PERFCOUNTERS
2154 mono_perfcounters->loader_bytes += size;
2156 res = mono_mempool_alloc (domain->mp, size);
2157 mono_domain_unlock (domain);
2163 * mono_domain_alloc0:
2165 * LOCKING: Acquires the domain lock.
2168 mono_domain_alloc0 (MonoDomain *domain, guint size)
2172 mono_domain_lock (domain);
2173 #ifndef DISABLE_PERFCOUNTERS
2174 mono_perfcounters->loader_bytes += size;
2176 res = mono_mempool_alloc0 (domain->mp, size);
2177 mono_domain_unlock (domain);
2183 * mono_domain_code_reserve:
2185 * LOCKING: Acquires the domain lock.
2188 mono_domain_code_reserve (MonoDomain *domain, int size)
2192 mono_domain_lock (domain);
2193 res = mono_code_manager_reserve (domain->code_mp, size);
2194 mono_domain_unlock (domain);
2200 * mono_domain_code_reserve_align:
2202 * LOCKING: Acquires the domain lock.
2205 mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment)
2209 mono_domain_lock (domain);
2210 res = mono_code_manager_reserve_align (domain->code_mp, size, alignment);
2211 mono_domain_unlock (domain);
2217 * mono_domain_code_commit:
2219 * LOCKING: Acquires the domain lock.
2222 mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize)
2224 mono_domain_lock (domain);
2225 mono_code_manager_commit (domain->code_mp, data, size, newsize);
2226 mono_domain_unlock (domain);
2229 #if defined(__native_client_codegen__) && defined(__native_client__)
2231 * Given the temporary buffer (allocated by mono_domain_code_reserve) into which
2232 * we are generating code, return a pointer to the destination in the dynamic
2233 * code segment into which the code will be copied when mono_domain_code_commit
2235 * LOCKING: Acquires the domain lock.
2238 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2241 mono_domain_lock (domain);
2242 dest = nacl_code_manager_get_code_dest (domain->code_mp, data);
2243 mono_domain_unlock (domain);
2248 * Convenience function which calls mono_domain_code_commit to validate and copy
2249 * the code. The caller sets *buf_base and *buf_size to the start and size of
2250 * the buffer (allocated by mono_domain_code_reserve), and *code_end to the byte
2251 * after the last instruction byte. On return, *buf_base will point to the start
2252 * of the copied in the code segment, and *code_end will point after the end of
2256 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2258 guint8 *tmp = nacl_domain_get_code_dest (domain, *buf_base);
2259 mono_domain_code_commit (domain, *buf_base, buf_size, *code_end - *buf_base);
2260 *code_end = tmp + (*code_end - *buf_base);
2266 /* no-op versions of Native Client functions */
2269 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2275 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2282 * mono_domain_code_foreach:
2283 * Iterate over the code thunks of the code manager of @domain.
2285 * The @func callback MUST not take any locks. If it really needs to, it must respect
2286 * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety
2287 * LOCKING: Acquires the domain lock.
2291 mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data)
2293 mono_domain_lock (domain);
2294 mono_code_manager_foreach (domain->code_mp, func, user_data);
2295 mono_domain_unlock (domain);
2300 mono_context_set (MonoAppContext * new_context)
2302 SET_APPCONTEXT (new_context);
2306 mono_context_get (void)
2308 return GET_APPCONTEXT ();
2311 /* LOCKING: the caller holds the lock for this domain */
2313 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
2315 /* The first entry in the array is the index of the next free slot
2316 * and the total size of the array
2319 if (domain->static_data_array) {
2320 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
2321 next = GPOINTER_TO_INT (domain->static_data_array [0]);
2323 /* 'data' is allocated by alloc_fixed */
2324 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2));
2325 mono_gc_memmove (new_array, domain->static_data_array, sizeof (gpointer) * size);
2327 new_array [1] = GINT_TO_POINTER (size);
2328 mono_gc_free_fixed (domain->static_data_array);
2329 domain->static_data_array = new_array;
2333 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, MONO_GC_ROOT_DESCR_FOR_FIXED (size));
2335 new_array [0] = GINT_TO_POINTER (next);
2336 new_array [1] = GINT_TO_POINTER (size);
2337 domain->static_data_array = new_array;
2339 domain->static_data_array [next++] = data;
2340 domain->static_data_array [0] = GINT_TO_POINTER (next);
2344 mono_get_corlib (void)
2346 return mono_defaults.corlib;
2350 mono_get_object_class (void)
2352 return mono_defaults.object_class;
2356 mono_get_byte_class (void)
2358 return mono_defaults.byte_class;
2362 mono_get_void_class (void)
2364 return mono_defaults.void_class;
2368 mono_get_boolean_class (void)
2370 return mono_defaults.boolean_class;
2374 mono_get_sbyte_class (void)
2376 return mono_defaults.sbyte_class;
2380 mono_get_int16_class (void)
2382 return mono_defaults.int16_class;
2386 mono_get_uint16_class (void)
2388 return mono_defaults.uint16_class;
2392 mono_get_int32_class (void)
2394 return mono_defaults.int32_class;
2398 mono_get_uint32_class (void)
2400 return mono_defaults.uint32_class;
2404 mono_get_intptr_class (void)
2406 return mono_defaults.int_class;
2410 mono_get_uintptr_class (void)
2412 return mono_defaults.uint_class;
2416 mono_get_int64_class (void)
2418 return mono_defaults.int64_class;
2422 mono_get_uint64_class (void)
2424 return mono_defaults.uint64_class;
2428 mono_get_single_class (void)
2430 return mono_defaults.single_class;
2434 mono_get_double_class (void)
2436 return mono_defaults.double_class;
2440 mono_get_char_class (void)
2442 return mono_defaults.char_class;
2446 mono_get_string_class (void)
2448 return mono_defaults.string_class;
2452 mono_get_enum_class (void)
2454 return mono_defaults.enum_class;
2458 mono_get_array_class (void)
2460 return mono_defaults.array_class;
2464 mono_get_thread_class (void)
2466 return mono_defaults.thread_class;
2470 mono_get_exception_class (void)
2472 return mono_defaults.exception_class;
2476 static char* get_attribute_value (const gchar **attribute_names,
2477 const gchar **attribute_values,
2478 const char *att_name)
2481 for (n=0; attribute_names[n] != NULL; n++) {
2482 if (strcmp (attribute_names[n], att_name) == 0)
2483 return g_strdup (attribute_values[n]);
2488 static void start_element (GMarkupParseContext *context,
2489 const gchar *element_name,
2490 const gchar **attribute_names,
2491 const gchar **attribute_values,
2495 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2497 if (strcmp (element_name, "configuration") == 0) {
2498 app_config->configuration_count++;
2501 if (strcmp (element_name, "startup") == 0) {
2502 app_config->startup_count++;
2506 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2509 if (strcmp (element_name, "requiredRuntime") == 0) {
2510 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2511 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2512 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2513 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2517 static void end_element (GMarkupParseContext *context,
2518 const gchar *element_name,
2522 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2524 if (strcmp (element_name, "configuration") == 0) {
2525 app_config->configuration_count--;
2526 } else if (strcmp (element_name, "startup") == 0) {
2527 app_config->startup_count--;
2531 static const GMarkupParser
2540 static AppConfigInfo *
2541 app_config_parse (const char *exe_filename)
2543 AppConfigInfo *app_config;
2544 GMarkupParseContext *context;
2547 const char *bundled_config;
2548 char *config_filename;
2550 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2552 if (bundled_config) {
2553 text = g_strdup (bundled_config);
2554 len = strlen (text);
2556 config_filename = g_strconcat (exe_filename, ".config", NULL);
2558 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2559 g_free (config_filename);
2562 g_free (config_filename);
2565 app_config = g_new0 (AppConfigInfo, 1);
2567 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2568 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2569 g_markup_parse_context_end_parse (context, NULL);
2571 g_markup_parse_context_free (context);
2577 app_config_free (AppConfigInfo* app_config)
2580 GSList *list = app_config->supported_runtimes;
2581 while (list != NULL) {
2582 rt = (char*)list->data;
2584 list = g_slist_next (list);
2586 g_slist_free (app_config->supported_runtimes);
2587 g_free (app_config->required_runtime);
2588 g_free (app_config);
2592 static const MonoRuntimeInfo*
2593 get_runtime_by_version (const char *version)
2596 int max = G_N_ELEMENTS (supported_runtimes);
2602 for (n=0; n<max; n++) {
2603 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2604 return &supported_runtimes[n];
2607 vlen = strlen (version);
2608 if (vlen >= 4 && version [1] - '0' >= 4) {
2609 for (n=0; n<max; n++) {
2610 if (strncmp (version, supported_runtimes[n].runtime_version, 4) == 0)
2611 return &supported_runtimes[n];
2619 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2621 AppConfigInfo* app_config;
2623 const MonoRuntimeInfo* runtime = NULL;
2624 MonoImage *image = NULL;
2626 app_config = app_config_parse (exe_file);
2628 if (app_config != NULL) {
2629 /* Check supportedRuntime elements, if none is supported, fail.
2630 * If there are no such elements, look for a requiredRuntime element.
2632 if (app_config->supported_runtimes != NULL) {
2634 GSList *list = app_config->supported_runtimes;
2635 while (list != NULL) {
2636 version = (char*) list->data;
2637 runtime = get_runtime_by_version (version);
2638 if (runtime != NULL)
2639 runtimes [n++] = runtime;
2640 list = g_slist_next (list);
2642 runtimes [n] = NULL;
2643 app_config_free (app_config);
2647 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2648 if (app_config->required_runtime != NULL) {
2649 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2650 runtimes [1] = NULL;
2651 app_config_free (app_config);
2654 app_config_free (app_config);
2657 /* Look for a runtime with the exact version */
2658 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2661 image = mono_image_open (exe_file, NULL);
2663 if (image == NULL) {
2664 /* The image is wrong or the file was not found. In this case return
2665 * a default runtime and leave to the initialization method the work of
2666 * reporting the error.
2668 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2669 runtimes [1] = NULL;
2675 runtimes [0] = get_runtime_by_version (image->version);
2676 runtimes [1] = NULL;
2681 * mono_get_runtime_info:
2683 * Returns: the version of the current runtime instance.
2685 const MonoRuntimeInfo*
2686 mono_get_runtime_info (void)
2688 return current_runtime;
2692 mono_debugger_check_runtime_version (const char *filename)
2694 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2695 const MonoRuntimeInfo *rinfo;
2698 get_runtimes_from_exe (filename, &image, runtimes);
2699 rinfo = runtimes [0];
2702 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2704 if (rinfo != current_runtime)
2705 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2706 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2707 filename, rinfo->runtime_version);
2713 * mono_framework_version:
2715 * Return the major version of the framework curently executing.
2718 mono_framework_version (void)
2720 return current_runtime->framework_version [0] - '0';