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/atomic.h>
21 #include <mono/utils/mono-compiler.h>
22 #include <mono/utils/mono-logger-internal.h>
23 #include <mono/utils/mono-membar.h>
24 #include <mono/utils/mono-counters.h>
25 #include <mono/utils/hazard-pointer.h>
26 #include <mono/utils/mono-tls.h>
27 #include <mono/utils/mono-mmap.h>
28 #include <mono/utils/mono-threads.h>
29 #include <mono/metadata/object.h>
30 #include <mono/metadata/object-internals.h>
31 #include <mono/metadata/domain-internals.h>
32 #include <mono/metadata/class-internals.h>
33 #include <mono/metadata/assembly.h>
34 #include <mono/metadata/exception.h>
35 #include <mono/metadata/metadata-internals.h>
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/appdomain.h>
38 #include <mono/metadata/mono-debug-debugger.h>
39 #include <mono/metadata/mono-config.h>
40 #include <mono/metadata/threads-types.h>
41 #include <mono/metadata/runtime.h>
42 #include <metadata/threads.h>
43 #include <metadata/profiler-private.h>
44 #include <mono/metadata/coree.h>
46 //#define DEBUG_DOMAIN_UNLOAD 1
48 /* we need to use both the Tls* functions and __thread because
49 * some archs may generate faster jit code with one meachanism
50 * or the other (we used to do it because tls slots were GC-tracked,
51 * but we can't depend on this).
53 static MonoNativeTlsKey appdomain_thread_id;
55 #ifdef MONO_HAVE_FAST_TLS
57 MONO_FAST_TLS_DECLARE(tls_appdomain);
59 #define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain))
61 #define SET_APPDOMAIN(x) do { \
62 MonoThreadInfo *info; \
63 MONO_FAST_TLS_SET (tls_appdomain,x); \
64 mono_native_tls_set_value (appdomain_thread_id, x); \
65 mono_gc_set_current_thread_appdomain (x); \
66 info = mono_thread_info_current (); \
68 mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x)); \
71 #else /* !MONO_HAVE_FAST_TLS */
73 #define GET_APPDOMAIN() ((MonoDomain *)mono_native_tls_get_value (appdomain_thread_id))
74 #define SET_APPDOMAIN(x) do { \
75 MonoThreadInfo *info; \
76 mono_native_tls_set_value (appdomain_thread_id, x); \
77 mono_gc_set_current_thread_appdomain (x); \
78 info = mono_thread_info_current (); \
80 mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x)); \
85 #define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext)
86 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x))
88 static guint16 appdomain_list_size = 0;
89 static guint16 appdomain_next = 0;
90 static MonoDomain **appdomains_list = NULL;
91 static MonoImage *exe_image;
92 static gboolean debug_domain_unload;
94 gboolean mono_dont_free_domains;
96 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
97 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
98 static CRITICAL_SECTION appdomains_mutex;
100 static MonoDomain *mono_root_domain = NULL;
102 /* some statistics */
103 static int max_domain_code_size = 0;
104 static int max_domain_code_alloc = 0;
105 static int total_domain_code_alloc = 0;
107 /* AppConfigInfo: Information about runtime versions supported by an
111 GSList *supported_runtimes;
112 char *required_runtime;
113 int configuration_count;
117 static const MonoRuntimeInfo *current_runtime = NULL;
119 static MonoJitInfoFindInAot jit_info_find_in_aot_func = 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}, {3,0,0,0} } },
125 {"v2.0.50727","2.0", { {2,0,0,0}, { 8,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
126 {"v4.0.30319","4.5", { {4,0,0,0}, {10,0,0,0}, {4,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}, {4,0,0,0} } },
128 {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
129 {"mobile", "2.1", { {2,0,5,0}, {10,0,0,0}, {2,0,5,0}, {2,0,5,0} } },
130 {"moonlight", "2.1", { {2,0,5,0}, { 9,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
134 /* The stable runtime version */
135 #define DEFAULT_RUNTIME_VERSION "v2.0.50727"
137 /* Callbacks installed by the JIT */
138 static MonoCreateDomainFunc create_domain_hook;
139 static MonoFreeDomainFunc free_domain_hook;
141 /* This is intentionally not in the header file, so people don't misuse it. */
142 extern void _mono_debug_init_corlib (MonoDomain *domain);
145 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
147 static const MonoRuntimeInfo*
148 get_runtime_by_version (const char *version);
151 mono_domain_get_tls_key (void)
153 return appdomain_thread_id;
157 mono_domain_get_tls_offset (void)
160 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
161 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
166 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
167 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
168 #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)
170 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
171 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
173 #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
174 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->d.method == JIT_INFO_TOMBSTONE_MARKER)
176 #define JIT_INFO_TABLE_HAZARD_INDEX 0
177 #define JIT_INFO_HAZARD_INDEX 1
180 jit_info_table_num_elements (MonoJitInfoTable *table)
183 int num_elements = 0;
185 for (i = 0; i < table->num_chunks; ++i) {
186 MonoJitInfoTableChunk *chunk = table->chunks [i];
187 int chunk_num_elements = chunk->num_elements;
190 for (j = 0; j < chunk_num_elements; ++j) {
191 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
199 static MonoJitInfoTableChunk*
200 jit_info_table_new_chunk (void)
202 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
208 static MonoJitInfoTable *
209 jit_info_table_new (MonoDomain *domain)
211 MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
213 table->domain = domain;
214 table->num_chunks = 1;
215 table->chunks [0] = jit_info_table_new_chunk ();
221 jit_info_table_free (MonoJitInfoTable *table)
224 int num_chunks = table->num_chunks;
225 MonoDomain *domain = table->domain;
227 mono_domain_lock (domain);
229 table->domain->num_jit_info_tables--;
230 if (table->domain->num_jit_info_tables <= 1) {
233 for (list = table->domain->jit_info_free_queue; list; list = list->next)
236 g_slist_free (table->domain->jit_info_free_queue);
237 table->domain->jit_info_free_queue = NULL;
240 /* At this point we assume that there are no other threads
241 still accessing the table, so we don't have to worry about
242 hazardous pointers. */
244 for (i = 0; i < num_chunks; ++i) {
245 MonoJitInfoTableChunk *chunk = table->chunks [i];
249 if (--chunk->refcount > 0)
252 num_elements = chunk->num_elements;
253 for (j = 0; j < num_elements; ++j) {
254 MonoJitInfo *ji = chunk->data [j];
256 if (IS_JIT_INFO_TOMBSTONE (ji))
263 mono_domain_unlock (domain);
268 /* The jit_info_table is sorted in ascending order by the end
269 * addresses of the compiled methods. The reason why we have to do
270 * this is that once we introduce tombstones, it becomes possible for
271 * code ranges to overlap, and if we sort by code start and insert at
272 * the back of the table, we cannot guarantee that we won't overlook
275 * There are actually two possible ways to do the sorting and
276 * inserting which work with our lock-free mechanism:
278 * 1. Sort by start address and insert at the front. When looking for
279 * an entry, find the last one with a start address lower than the one
280 * you're looking for, then work your way to the front of the table.
282 * 2. Sort by end address and insert at the back. When looking for an
283 * entry, find the first one with an end address higher than the one
284 * you're looking for, then work your way to the end of the table.
286 * We chose the latter out of convenience.
289 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
291 int left = 0, right = table->num_chunks;
293 g_assert (left < right);
296 int pos = (left + right) / 2;
297 MonoJitInfoTableChunk *chunk = table->chunks [pos];
299 if (addr < chunk->last_code_end)
303 } while (left < right);
304 g_assert (left == right);
306 if (left >= table->num_chunks)
307 return table->num_chunks - 1;
312 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
314 int left = 0, right = chunk->num_elements;
316 while (left < right) {
317 int pos = (left + right) / 2;
318 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
319 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
326 g_assert (left == right);
332 jit_info_table_find (MonoJitInfoTable *table, MonoThreadHazardPointers *hp, gint8 *addr)
337 chunk_pos = jit_info_table_index (table, (gint8*)addr);
338 g_assert (chunk_pos < table->num_chunks);
340 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
342 /* We now have a position that's very close to that of the
343 first element whose end address is higher than the one
344 we're looking for. If we don't have the exact position,
345 then we have a position below that one, so we'll just
346 search upward until we find our element. */
348 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
350 while (pos < chunk->num_elements) {
351 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
355 if (IS_JIT_INFO_TOMBSTONE (ji)) {
356 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
359 if ((gint8*)addr >= (gint8*)ji->code_start
360 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
361 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
365 /* If we find a non-tombstone element which is already
366 beyond what we're looking for, we have to end the
368 if ((gint8*)addr < (gint8*)ji->code_start)
374 } while (chunk_pos < table->num_chunks);
378 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
383 * mono_jit_info_table_find_internal:
385 * If TRY_AOT is FALSE, avoid loading information for missing methods from AOT images, which is currently not async safe.
386 * In this case, only those AOT methods will be found whose jit info is already loaded.
387 * ASYNC SAFETY: When called in an async context (mono_thread_info_is_async_context ()), this is async safe.
388 * In this case, the returned MonoJitInfo might not have metadata information, in particular,
389 * mono_jit_info_get_method () could fail.
392 mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot)
394 MonoJitInfoTable *table;
395 MonoJitInfo *ji, *module_ji;
396 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
398 ++mono_stats.jit_info_table_lookup_count;
400 /* First we have to get the domain's jit_info_table. This is
401 complicated by the fact that a writer might substitute a
402 new table and free the old one. What the writer guarantees
403 us is that it looks at the hazard pointers after it has
404 changed the jit_info_table pointer. So, if we guard the
405 table by a hazard pointer and make sure that the pointer is
406 still there after we've made it hazardous, we don't have to
407 worry about the writer freeing the table. */
408 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
410 ji = jit_info_table_find (table, hp, (gint8*)addr);
412 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
416 /* Maybe its an AOT module */
417 if (try_aot && mono_root_domain && mono_root_domain->aot_modules) {
418 table = get_hazardous_pointer ((gpointer volatile*)&mono_root_domain->aot_modules, hp, JIT_INFO_TABLE_HAZARD_INDEX);
419 module_ji = jit_info_table_find (table, hp, (gint8*)addr);
421 ji = jit_info_find_in_aot_func (domain, module_ji->d.image, addr);
423 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
430 mono_jit_info_table_find (MonoDomain *domain, char *addr)
432 return mono_jit_info_table_find_internal (domain, addr, TRUE);
435 static G_GNUC_UNUSED void
436 jit_info_table_check (MonoJitInfoTable *table)
440 for (i = 0; i < table->num_chunks; ++i) {
441 MonoJitInfoTableChunk *chunk = table->chunks [i];
444 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
445 if (chunk->refcount > 10)
446 printf("warning: chunk refcount is %d\n", chunk->refcount);
447 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
449 for (j = 0; j < chunk->num_elements; ++j) {
450 MonoJitInfo *this = chunk->data [j];
453 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
455 if (j < chunk->num_elements - 1)
456 next = chunk->data [j + 1];
457 else if (i < table->num_chunks - 1) {
460 for (k = i + 1; k < table->num_chunks; ++k)
461 if (table->chunks [k]->num_elements > 0)
464 if (k >= table->num_chunks)
467 g_assert (table->chunks [k]->num_elements > 0);
468 next = table->chunks [k]->data [0];
472 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
477 static MonoJitInfoTable*
478 jit_info_table_realloc (MonoJitInfoTable *old)
481 int num_elements = jit_info_table_num_elements (old);
484 int new_chunk, new_element;
485 MonoJitInfoTable *new;
487 /* number of needed places for elements needed */
488 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
489 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
490 if (num_chunks == 0) {
491 g_assert (num_elements == 0);
492 return jit_info_table_new (old->domain);
494 g_assert (num_chunks > 0);
496 new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
497 new->domain = old->domain;
498 new->num_chunks = num_chunks;
500 for (i = 0; i < num_chunks; ++i)
501 new->chunks [i] = jit_info_table_new_chunk ();
505 for (i = 0; i < old->num_chunks; ++i) {
506 MonoJitInfoTableChunk *chunk = old->chunks [i];
507 int chunk_num_elements = chunk->num_elements;
510 for (j = 0; j < chunk_num_elements; ++j) {
511 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
512 g_assert (new_chunk < num_chunks);
513 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
514 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
515 new->chunks [new_chunk]->num_elements = new_element;
523 if (new_chunk < num_chunks) {
524 g_assert (new_chunk == num_chunks - 1);
525 new->chunks [new_chunk]->num_elements = new_element;
526 g_assert (new->chunks [new_chunk]->num_elements > 0);
529 for (i = 0; i < num_chunks; ++i) {
530 MonoJitInfoTableChunk *chunk = new->chunks [i];
531 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
533 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
540 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
542 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
543 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
545 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
547 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
548 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
550 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
551 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
553 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
554 + new1->data [new1->num_elements - 1]->code_size;
555 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
556 + new2->data [new2->num_elements - 1]->code_size;
562 static MonoJitInfoTable*
563 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
565 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
566 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
569 new_table->domain = table->domain;
570 new_table->num_chunks = table->num_chunks + 1;
573 for (i = 0; i < table->num_chunks; ++i) {
574 if (table->chunks [i] == chunk) {
575 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
578 new_table->chunks [j] = table->chunks [i];
579 ++new_table->chunks [j]->refcount;
584 g_assert (j == new_table->num_chunks);
589 static MonoJitInfoTableChunk*
590 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
592 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
596 for (i = 0; i < old->num_elements; ++i) {
597 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
598 new->data [j++] = old->data [i];
601 new->num_elements = j;
602 if (new->num_elements > 0)
603 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
605 new->last_code_end = old->last_code_end;
610 static MonoJitInfoTable*
611 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
613 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
614 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
617 new_table->domain = table->domain;
618 new_table->num_chunks = table->num_chunks;
621 for (i = 0; i < table->num_chunks; ++i) {
622 if (table->chunks [i] == chunk)
623 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
625 new_table->chunks [j] = table->chunks [i];
626 ++new_table->chunks [j]->refcount;
631 g_assert (j == new_table->num_chunks);
636 /* As we add an element to the table the case can arise that the chunk
637 * to which we need to add is already full. In that case we have to
638 * allocate a new table and do something about that chunk. We have
639 * several strategies:
641 * If the number of elements in the table is below the low watermark
642 * or above the high watermark, we reallocate the whole table.
643 * Otherwise we only concern ourselves with the overflowing chunk:
645 * If there are no tombstones in the chunk then we split the chunk in
646 * two, each half full.
648 * If the chunk does contain tombstones, we just make a new copy of
649 * the chunk without the tombstones, which will have room for at least
650 * the one element we have to add.
652 static MonoJitInfoTable*
653 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
655 int num_elements = jit_info_table_num_elements (table);
658 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
659 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
660 //printf ("reallocing table\n");
661 return jit_info_table_realloc (table);
664 /* count the number of non-tombstone elements in the chunk */
666 for (i = 0; i < chunk->num_elements; ++i) {
667 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
671 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
672 //printf ("splitting chunk\n");
673 return jit_info_table_copy_and_split_chunk (table, chunk);
676 //printf ("purifying chunk\n");
677 return jit_info_table_copy_and_purify_chunk (table, chunk);
680 /* We add elements to the table by first making space for them by
681 * shifting the elements at the back to the right, one at a time.
682 * This results in duplicate entries during the process, but during
683 * all the time the table is in a sorted state. Also, when an element
684 * is replaced by another one, the element that replaces it has an end
685 * address that is equal to or lower than that of the replaced
686 * element. That property is necessary to guarantee that when
687 * searching for an element we end up at a position not higher than
688 * the one we're looking for (i.e. we either find the element directly
689 * or we end up to the left of it).
692 jit_info_table_add (MonoDomain *domain, MonoJitInfoTable *volatile *table_ptr, MonoJitInfo *ji)
694 MonoJitInfoTable *table;
695 MonoJitInfoTableChunk *chunk;
703 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
704 g_assert (chunk_pos < table->num_chunks);
705 chunk = table->chunks [chunk_pos];
707 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
708 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
710 /* Debugging code, should be removed. */
711 //jit_info_table_check (new_table);
713 *table_ptr = new_table;
714 mono_memory_barrier ();
715 domain->num_jit_info_tables++;
716 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free, TRUE, FALSE);
722 /* Debugging code, should be removed. */
723 //jit_info_table_check (table);
725 num_elements = chunk->num_elements;
727 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
729 /* First we need to size up the chunk by one, by copying the
730 last item, or inserting the first one, if the table is
732 if (num_elements > 0)
733 chunk->data [num_elements] = chunk->data [num_elements - 1];
735 chunk->data [0] = ji;
736 mono_memory_write_barrier ();
737 chunk->num_elements = ++num_elements;
739 /* Shift the elements up one by one. */
740 for (i = num_elements - 2; i >= pos; --i) {
741 mono_memory_write_barrier ();
742 chunk->data [i + 1] = chunk->data [i];
745 /* Now we have room and can insert the new item. */
746 mono_memory_write_barrier ();
747 chunk->data [pos] = ji;
749 /* Set the high code end address chunk entry. */
750 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
751 + chunk->data [chunk->num_elements - 1]->code_size;
753 /* Debugging code, should be removed. */
754 //jit_info_table_check (table);
758 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
760 g_assert (ji->d.method != NULL);
762 mono_domain_lock (domain);
764 ++mono_stats.jit_info_table_insert_count;
766 jit_info_table_add (domain, &domain->jit_info_table, ji);
768 mono_domain_unlock (domain);
772 mono_jit_info_make_tombstone (MonoJitInfo *ji)
774 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
776 tombstone->code_start = ji->code_start;
777 tombstone->code_size = ji->code_size;
778 tombstone->d.method = JIT_INFO_TOMBSTONE_MARKER;
784 * LOCKING: domain lock
787 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
789 if (domain->num_jit_info_tables <= 1) {
790 /* Can it actually happen that we only have one table
791 but ji is still hazardous? */
792 mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
794 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
799 jit_info_table_remove (MonoJitInfoTable *table, MonoJitInfo *ji)
801 MonoJitInfoTableChunk *chunk;
802 gpointer start = ji->code_start;
805 chunk_pos = jit_info_table_index (table, start);
806 g_assert (chunk_pos < table->num_chunks);
808 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
811 chunk = table->chunks [chunk_pos];
813 while (pos < chunk->num_elements) {
814 if (chunk->data [pos] == ji)
817 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
818 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
819 <= (guint8*)ji->code_start + ji->code_size);
826 } while (chunk_pos < table->num_chunks);
829 g_assert (chunk->data [pos] == ji);
831 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
833 /* Debugging code, should be removed. */
834 //jit_info_table_check (table);
838 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
840 MonoJitInfoTable *table;
842 mono_domain_lock (domain);
843 table = domain->jit_info_table;
845 ++mono_stats.jit_info_table_remove_count;
847 jit_info_table_remove (table, ji);
849 mono_jit_info_free_or_queue (domain, ji);
851 mono_domain_unlock (domain);
855 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
859 mono_appdomains_lock ();
862 * We reuse MonoJitInfoTable to store AOT module info,
863 * this gives us async-safe lookup.
865 g_assert (mono_root_domain);
866 if (!mono_root_domain->aot_modules) {
867 mono_root_domain->num_jit_info_tables ++;
868 mono_root_domain->aot_modules = jit_info_table_new (mono_root_domain);
871 ji = g_new0 (MonoJitInfo, 1);
873 ji->code_start = start;
874 ji->code_size = (guint8*)end - (guint8*)start;
875 jit_info_table_add (mono_root_domain, &mono_root_domain->aot_modules, ji);
877 mono_appdomains_unlock ();
881 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
883 jit_info_find_in_aot_func = func;
887 mono_jit_info_get_code_start (MonoJitInfo* ji)
889 return ji->code_start;
893 mono_jit_info_get_code_size (MonoJitInfo* ji)
895 return ji->code_size;
899 mono_jit_info_get_method (MonoJitInfo* ji)
901 g_assert (!ji->async);
906 jit_info_key_extract (gpointer value)
908 MonoJitInfo *info = (MonoJitInfo*)value;
910 return info->d.method;
914 jit_info_next_value (gpointer value)
916 MonoJitInfo *info = (MonoJitInfo*)value;
918 return (gpointer*)&info->next_jit_code_hash;
922 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
924 mono_internal_hash_table_init (jit_code_hash,
925 mono_aligned_addr_hash,
926 jit_info_key_extract,
927 jit_info_next_value);
931 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
933 if (ji->has_generic_jit_info)
934 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
940 * mono_jit_info_get_generic_sharing_context:
943 * Returns the jit info's generic sharing context, or NULL if it
946 MonoGenericSharingContext*
947 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
949 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
952 return gi->generic_sharing_context;
958 * mono_jit_info_set_generic_sharing_context:
960 * @gsctx: a generic sharing context
962 * Sets the jit info's generic sharing context. The jit info must
963 * have memory allocated for the context.
966 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
968 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
972 gi->generic_sharing_context = gsctx;
975 MonoTryBlockHoleTableJitInfo*
976 mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
978 if (ji->has_try_block_holes) {
979 char *ptr = (char*)&ji->clauses [ji->num_clauses];
980 if (ji->has_generic_jit_info)
981 ptr += sizeof (MonoGenericJitInfo);
982 return (MonoTryBlockHoleTableJitInfo*)ptr;
989 mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
991 if (ji->has_arch_eh_info) {
992 char *ptr = (char*)&ji->clauses [ji->num_clauses];
993 if (ji->has_generic_jit_info)
994 ptr += sizeof (MonoGenericJitInfo);
995 if (ji->has_try_block_holes)
996 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
997 return (MonoArchEHJitInfo*)ptr;
1004 mono_jit_info_get_cas_info (MonoJitInfo *ji)
1006 if (ji->has_cas_info) {
1007 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1008 if (ji->has_generic_jit_info)
1009 ptr += sizeof (MonoGenericJitInfo);
1010 if (ji->has_try_block_holes)
1011 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
1012 if (ji->has_arch_eh_info)
1013 ptr += sizeof (MonoArchEHJitInfo);
1014 return (MonoMethodCasInfo*)ptr;
1020 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
1021 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
1023 static LockFreeMempool*
1024 lock_free_mempool_new (void)
1026 return g_new0 (LockFreeMempool, 1);
1030 lock_free_mempool_free (LockFreeMempool *mp)
1032 LockFreeMempoolChunk *chunk, *next;
1037 mono_vfree (chunk, mono_pagesize ());
1044 * This is async safe
1046 static LockFreeMempoolChunk*
1047 lock_free_mempool_chunk_new (LockFreeMempool *mp, int len)
1049 LockFreeMempoolChunk *chunk, *prev;
1052 size = mono_pagesize ();
1053 while (size - sizeof (LockFreeMempoolChunk) < len)
1054 size += mono_pagesize ();
1055 chunk = mono_valloc (0, size, MONO_MMAP_READ|MONO_MMAP_WRITE);
1057 chunk->mem = ALIGN_PTR_TO ((char*)chunk + sizeof (LockFreeMempoolChunk), 16);
1058 chunk->size = ((char*)chunk + size) - (char*)chunk->mem;
1061 /* Add to list of chunks lock-free */
1064 if (InterlockedCompareExchangePointer ((volatile gpointer*)&mp->chunks, chunk, prev) == prev)
1073 * This is async safe
1076 lock_free_mempool_alloc0 (LockFreeMempool *mp, guint size)
1078 LockFreeMempoolChunk *chunk;
1082 // FIXME: Free the allocator
1084 size = ALIGN_TO (size, 8);
1085 chunk = mp->current;
1087 chunk = lock_free_mempool_chunk_new (mp, size);
1088 mono_memory_barrier ();
1090 mp->current = chunk;
1093 /* The code below is lock-free, 'chunk' is shared state */
1094 oldpos = InterlockedExchangeAdd (&chunk->pos, size);
1095 if (oldpos + size > chunk->size) {
1096 chunk = lock_free_mempool_chunk_new (mp, size);
1097 g_assert (chunk->pos + size <= chunk->size);
1100 mono_memory_barrier ();
1101 mp->current = chunk;
1103 res = (char*)chunk->mem + oldpos;
1110 mono_install_create_domain_hook (MonoCreateDomainFunc func)
1112 create_domain_hook = func;
1116 mono_install_free_domain_hook (MonoFreeDomainFunc func)
1118 free_domain_hook = func;
1122 * mono_string_equal:
1123 * @s1: First string to compare
1124 * @s2: Second string to compare
1126 * Returns FALSE if the strings differ.
1129 mono_string_equal (MonoString *s1, MonoString *s2)
1131 int l1 = mono_string_length (s1);
1132 int l2 = mono_string_length (s2);
1139 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
1144 * @s: the string to hash
1146 * Returns the hash for the string.
1149 mono_string_hash (MonoString *s)
1151 const guint16 *p = mono_string_chars (s);
1152 int i, len = mono_string_length (s);
1155 for (i = 0; i < len; i++) {
1156 h = (h << 5) - h + *p;
1164 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1166 int len = GPOINTER_TO_INT (s1 [0]);
1167 if (len != GPOINTER_TO_INT (s2 [0]))
1170 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1174 mono_ptrarray_hash (gpointer *s)
1177 int len = GPOINTER_TO_INT (s [0]);
1180 for (i = 1; i < len; i++)
1181 hash += GPOINTER_TO_UINT (s [i]);
1187 * Allocate an id for domain and set domain->domain_id.
1188 * LOCKING: must be called while holding appdomains_mutex.
1189 * We try to assign low numbers to the domain, so it can be used
1190 * as an index in data tables to lookup domain-specific info
1191 * with minimal memory overhead. We also try not to reuse the
1192 * same id too quickly (to help debugging).
1195 domain_id_alloc (MonoDomain *domain)
1198 if (!appdomains_list) {
1199 appdomain_list_size = 2;
1200 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1202 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1203 if (!appdomains_list [i]) {
1209 for (i = 0; i < appdomain_next; ++i) {
1210 if (!appdomains_list [i]) {
1217 MonoDomain **new_list;
1218 int new_size = appdomain_list_size * 2;
1219 if (new_size >= (1 << 16))
1220 g_assert_not_reached ();
1221 id = appdomain_list_size;
1222 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1223 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1224 mono_gc_free_fixed (appdomains_list);
1225 appdomains_list = new_list;
1226 appdomain_list_size = new_size;
1228 domain->domain_id = id;
1229 appdomains_list [id] = domain;
1231 if (appdomain_next > appdomain_list_size)
1236 static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1237 static gpointer domain_gc_desc = NULL;
1238 static guint32 domain_shadow_serial = 0L;
1241 mono_domain_create (void)
1244 guint32 shadow_serial;
1246 mono_appdomains_lock ();
1247 shadow_serial = domain_shadow_serial++;
1249 if (!domain_gc_desc) {
1250 unsigned int i, bit = 0;
1251 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1252 bit = i / sizeof (gpointer);
1253 domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32);
1255 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1257 mono_appdomains_unlock ();
1259 #ifdef HAVE_BOEHM_GC
1261 * Boehm doesn't like roots inside GC allocated objects, and alloc_fixed returns
1262 * a GC_MALLOC-ed object, contrary to the api docs. This causes random crashes when
1263 * running the corlib test suite.
1264 * To solve this, we pass a NULL descriptor, and don't register roots.
1266 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL);
1268 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1269 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);
1271 domain->shadow_serial = shadow_serial;
1272 domain->domain = NULL;
1273 domain->setup = NULL;
1274 domain->friendly_name = NULL;
1275 domain->search_path = NULL;
1277 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1279 domain->mp = mono_mempool_new ();
1280 domain->code_mp = mono_code_manager_new ();
1281 domain->lock_free_mp = lock_free_mempool_new ();
1282 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1283 domain->domain_assemblies = NULL;
1284 domain->assembly_bindings = NULL;
1285 domain->assembly_bindings_parsed = FALSE;
1286 domain->class_vtable_array = g_ptr_array_new ();
1287 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1288 domain->static_data_array = NULL;
1289 mono_jit_code_hash_init (&domain->jit_code_hash);
1290 domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1291 domain->num_jit_info_tables = 1;
1292 domain->jit_info_table = jit_info_table_new (domain);
1293 domain->jit_info_free_queue = NULL;
1294 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1295 domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1297 InitializeCriticalSection (&domain->lock);
1298 InitializeCriticalSection (&domain->assemblies_lock);
1299 InitializeCriticalSection (&domain->jit_code_hash_lock);
1300 InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
1302 domain->method_rgctx_hash = NULL;
1304 mono_appdomains_lock ();
1305 domain_id_alloc (domain);
1306 mono_appdomains_unlock ();
1308 #ifndef DISABLE_PERFCOUNTERS
1309 mono_perfcounters->loader_appdomains++;
1310 mono_perfcounters->loader_total_appdomains++;
1313 mono_debug_domain_create (domain);
1315 if (create_domain_hook)
1316 create_domain_hook (domain);
1318 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1324 * mono_init_internal:
1326 * Creates the initial application domain and initializes the mono_defaults
1328 * This function is guaranteed to not run any IL code.
1329 * If exe_filename is not NULL, the method will determine the required runtime
1330 * from the exe configuration file or the version PE field.
1331 * If runtime_version is not NULL, that runtime version will be used.
1332 * Either exe_filename or runtime_version must be provided.
1334 * Returns: the initial domain.
1337 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1339 static MonoDomain *domain = NULL;
1340 MonoAssembly *ass = NULL;
1341 MonoImageOpenStatus status = MONO_IMAGE_OK;
1342 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1345 #ifdef DEBUG_DOMAIN_UNLOAD
1346 debug_domain_unload = TRUE;
1350 g_assert_not_reached ();
1353 /* Avoid system error message boxes. */
1354 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1361 #ifndef DISABLE_PERFCOUNTERS
1362 mono_perfcounters_init ();
1365 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1366 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1367 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1369 mono_gc_base_init ();
1371 MONO_FAST_TLS_INIT (tls_appdomain);
1372 mono_native_tls_alloc (&appdomain_thread_id, NULL);
1374 InitializeCriticalSection (&appdomains_mutex);
1376 mono_metadata_init ();
1377 mono_images_init ();
1378 mono_assemblies_init ();
1379 mono_classes_init ();
1380 mono_loader_init ();
1381 mono_reflection_init ();
1382 mono_runtime_init_tls ();
1384 /* FIXME: When should we release this memory? */
1385 MONO_GC_REGISTER_ROOT_FIXED (appdomains_list);
1387 domain = mono_domain_create ();
1388 mono_root_domain = domain;
1390 SET_APPDOMAIN (domain);
1392 /* Get a list of runtimes supported by the exe */
1393 if (exe_filename != NULL) {
1395 * This function will load the exe file as a MonoImage. We need to close it, but
1396 * that would mean it would be reloaded later. So instead, we save it to
1397 * exe_image, and close it during shutdown.
1399 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1402 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1404 exe_image = mono_image_open (exe_filename, NULL);
1406 mono_fixup_exe_image (exe_image);
1408 } else if (runtime_version != NULL) {
1409 runtimes [0] = get_runtime_by_version (runtime_version);
1410 runtimes [1] = NULL;
1413 if (runtimes [0] == NULL) {
1414 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1415 runtimes [0] = default_runtime;
1416 runtimes [1] = NULL;
1417 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1418 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1421 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1422 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1423 current_runtime = runtimes [n];
1424 ass = mono_assembly_load_corlib (current_runtime, &status);
1425 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1430 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1432 case MONO_IMAGE_ERROR_ERRNO: {
1433 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1434 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1435 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1436 g_free (corlib_file);
1439 case MONO_IMAGE_IMAGE_INVALID:
1440 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1441 mono_assembly_getrootdir ());
1443 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1444 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1445 mono_assembly_getrootdir ());
1448 /* to suppress compiler warning */
1454 mono_defaults.corlib = mono_assembly_get_image (ass);
1456 mono_defaults.object_class = mono_class_from_name (
1457 mono_defaults.corlib, "System", "Object");
1458 g_assert (mono_defaults.object_class != 0);
1460 mono_defaults.void_class = mono_class_from_name (
1461 mono_defaults.corlib, "System", "Void");
1462 g_assert (mono_defaults.void_class != 0);
1464 mono_defaults.boolean_class = mono_class_from_name (
1465 mono_defaults.corlib, "System", "Boolean");
1466 g_assert (mono_defaults.boolean_class != 0);
1468 mono_defaults.byte_class = mono_class_from_name (
1469 mono_defaults.corlib, "System", "Byte");
1470 g_assert (mono_defaults.byte_class != 0);
1472 mono_defaults.sbyte_class = mono_class_from_name (
1473 mono_defaults.corlib, "System", "SByte");
1474 g_assert (mono_defaults.sbyte_class != 0);
1476 mono_defaults.int16_class = mono_class_from_name (
1477 mono_defaults.corlib, "System", "Int16");
1478 g_assert (mono_defaults.int16_class != 0);
1480 mono_defaults.uint16_class = mono_class_from_name (
1481 mono_defaults.corlib, "System", "UInt16");
1482 g_assert (mono_defaults.uint16_class != 0);
1484 mono_defaults.int32_class = mono_class_from_name (
1485 mono_defaults.corlib, "System", "Int32");
1486 g_assert (mono_defaults.int32_class != 0);
1488 mono_defaults.uint32_class = mono_class_from_name (
1489 mono_defaults.corlib, "System", "UInt32");
1490 g_assert (mono_defaults.uint32_class != 0);
1492 mono_defaults.uint_class = mono_class_from_name (
1493 mono_defaults.corlib, "System", "UIntPtr");
1494 g_assert (mono_defaults.uint_class != 0);
1496 mono_defaults.int_class = mono_class_from_name (
1497 mono_defaults.corlib, "System", "IntPtr");
1498 g_assert (mono_defaults.int_class != 0);
1500 mono_defaults.int64_class = mono_class_from_name (
1501 mono_defaults.corlib, "System", "Int64");
1502 g_assert (mono_defaults.int64_class != 0);
1504 mono_defaults.uint64_class = mono_class_from_name (
1505 mono_defaults.corlib, "System", "UInt64");
1506 g_assert (mono_defaults.uint64_class != 0);
1508 mono_defaults.single_class = mono_class_from_name (
1509 mono_defaults.corlib, "System", "Single");
1510 g_assert (mono_defaults.single_class != 0);
1512 mono_defaults.double_class = mono_class_from_name (
1513 mono_defaults.corlib, "System", "Double");
1514 g_assert (mono_defaults.double_class != 0);
1516 mono_defaults.char_class = mono_class_from_name (
1517 mono_defaults.corlib, "System", "Char");
1518 g_assert (mono_defaults.char_class != 0);
1520 mono_defaults.string_class = mono_class_from_name (
1521 mono_defaults.corlib, "System", "String");
1522 g_assert (mono_defaults.string_class != 0);
1524 mono_defaults.enum_class = mono_class_from_name (
1525 mono_defaults.corlib, "System", "Enum");
1526 g_assert (mono_defaults.enum_class != 0);
1528 mono_defaults.array_class = mono_class_from_name (
1529 mono_defaults.corlib, "System", "Array");
1530 g_assert (mono_defaults.array_class != 0);
1532 mono_defaults.delegate_class = mono_class_from_name (
1533 mono_defaults.corlib, "System", "Delegate");
1534 g_assert (mono_defaults.delegate_class != 0 );
1536 mono_defaults.multicastdelegate_class = mono_class_from_name (
1537 mono_defaults.corlib, "System", "MulticastDelegate");
1538 g_assert (mono_defaults.multicastdelegate_class != 0 );
1540 mono_defaults.asyncresult_class = mono_class_from_name (
1541 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1543 g_assert (mono_defaults.asyncresult_class != 0 );
1545 mono_defaults.manualresetevent_class = mono_class_from_name (
1546 mono_defaults.corlib, "System.Threading", "ManualResetEvent");
1547 g_assert (mono_defaults.manualresetevent_class != 0 );
1549 mono_defaults.typehandle_class = mono_class_from_name (
1550 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1551 g_assert (mono_defaults.typehandle_class != 0);
1553 mono_defaults.methodhandle_class = mono_class_from_name (
1554 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1555 g_assert (mono_defaults.methodhandle_class != 0);
1557 mono_defaults.fieldhandle_class = mono_class_from_name (
1558 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1559 g_assert (mono_defaults.fieldhandle_class != 0);
1561 mono_defaults.systemtype_class = mono_class_from_name (
1562 mono_defaults.corlib, "System", "Type");
1563 g_assert (mono_defaults.systemtype_class != 0);
1565 mono_defaults.monotype_class = mono_class_from_name (
1566 mono_defaults.corlib, "System", "MonoType");
1567 g_assert (mono_defaults.monotype_class != 0);
1569 mono_defaults.exception_class = mono_class_from_name (
1570 mono_defaults.corlib, "System", "Exception");
1571 g_assert (mono_defaults.exception_class != 0);
1573 mono_defaults.threadabortexception_class = mono_class_from_name (
1574 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1575 g_assert (mono_defaults.threadabortexception_class != 0);
1577 mono_defaults.thread_class = mono_class_from_name (
1578 mono_defaults.corlib, "System.Threading", "Thread");
1579 g_assert (mono_defaults.thread_class != 0);
1581 mono_defaults.internal_thread_class = mono_class_from_name (
1582 mono_defaults.corlib, "System.Threading", "InternalThread");
1583 if (!mono_defaults.internal_thread_class) {
1584 /* This can happen with an old mscorlib */
1585 fprintf (stderr, "Corlib too old for this runtime.\n");
1586 fprintf (stderr, "Loaded from: %s\n",
1587 mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown");
1591 mono_defaults.appdomain_class = mono_class_from_name (
1592 mono_defaults.corlib, "System", "AppDomain");
1593 g_assert (mono_defaults.appdomain_class != 0);
1595 #ifndef DISABLE_REMOTING
1596 mono_defaults.transparent_proxy_class = mono_class_from_name (
1597 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1598 g_assert (mono_defaults.transparent_proxy_class != 0);
1600 mono_defaults.real_proxy_class = mono_class_from_name (
1601 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1602 g_assert (mono_defaults.real_proxy_class != 0);
1604 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1605 mono_defaults.corlib, "System", "MarshalByRefObject");
1606 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1608 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1609 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1610 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1613 mono_defaults.mono_method_message_class = mono_class_from_name (
1614 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1615 g_assert (mono_defaults.mono_method_message_class != 0);
1617 mono_defaults.field_info_class = mono_class_from_name (
1618 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1619 g_assert (mono_defaults.field_info_class != 0);
1621 mono_defaults.method_info_class = mono_class_from_name (
1622 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1623 g_assert (mono_defaults.method_info_class != 0);
1625 mono_defaults.stringbuilder_class = mono_class_from_name (
1626 mono_defaults.corlib, "System.Text", "StringBuilder");
1627 g_assert (mono_defaults.stringbuilder_class != 0);
1629 mono_defaults.math_class = mono_class_from_name (
1630 mono_defaults.corlib, "System", "Math");
1631 g_assert (mono_defaults.math_class != 0);
1633 mono_defaults.stack_frame_class = mono_class_from_name (
1634 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1635 g_assert (mono_defaults.stack_frame_class != 0);
1637 mono_defaults.stack_trace_class = mono_class_from_name (
1638 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1639 g_assert (mono_defaults.stack_trace_class != 0);
1641 mono_defaults.marshal_class = mono_class_from_name (
1642 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1643 g_assert (mono_defaults.marshal_class != 0);
1645 mono_defaults.typed_reference_class = mono_class_from_name (
1646 mono_defaults.corlib, "System", "TypedReference");
1647 g_assert (mono_defaults.typed_reference_class != 0);
1649 mono_defaults.argumenthandle_class = mono_class_from_name (
1650 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1651 g_assert (mono_defaults.argumenthandle_class != 0);
1653 mono_defaults.monitor_class = mono_class_from_name (
1654 mono_defaults.corlib, "System.Threading", "Monitor");
1655 g_assert (mono_defaults.monitor_class != 0);
1657 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1658 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1660 mono_defaults.executioncontext_class = mono_class_from_name (
1661 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1663 mono_defaults.internals_visible_class = mono_class_from_name (
1664 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1666 mono_defaults.critical_finalizer_object = mono_class_from_name (
1667 mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
1670 * mscorlib needs a little help, only now it can load its friends list (after we have
1671 * loaded the InternalsVisibleToAttribute), load it now
1673 mono_assembly_load_friends (ass);
1675 mono_defaults.safehandle_class = mono_class_from_name (
1676 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1678 mono_defaults.handleref_class = mono_class_from_name (
1679 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1681 mono_defaults.attribute_class = mono_class_from_name (
1682 mono_defaults.corlib, "System", "Attribute");
1684 mono_defaults.customattribute_data_class = mono_class_from_name (
1685 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1687 /* these are initialized lazily when COM features are used */
1689 mono_class_init (mono_defaults.array_class);
1690 mono_defaults.generic_nullable_class = mono_class_from_name (
1691 mono_defaults.corlib, "System", "Nullable`1");
1692 mono_defaults.generic_ilist_class = mono_class_from_name (
1693 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1694 mono_defaults.generic_ireadonlylist_class = mono_class_from_name (
1695 mono_defaults.corlib, "System.Collections.Generic", "IReadOnlyList`1");
1697 domain->friendly_name = g_path_get_basename (filename);
1699 _mono_debug_init_corlib (domain);
1707 * Creates the initial application domain and initializes the mono_defaults
1709 * This function is guaranteed to not run any IL code.
1710 * The runtime is initialized using the default runtime version.
1712 * Returns: the initial domain.
1715 mono_init (const char *domain_name)
1717 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1721 * mono_init_from_assembly:
1722 * @domain_name: name to give to the initial domain
1723 * @filename: filename to load on startup
1725 * Used by the runtime, users should use mono_jit_init instead.
1727 * Creates the initial application domain and initializes the mono_defaults
1729 * This function is guaranteed to not run any IL code.
1730 * The runtime is initialized using the runtime version required by the
1731 * provided executable. The version is determined by looking at the exe
1732 * configuration file and the version PE field)
1734 * Returns: the initial domain.
1737 mono_init_from_assembly (const char *domain_name, const char *filename)
1739 return mono_init_internal (domain_name, filename, NULL);
1743 * mono_init_version:
1745 * Used by the runtime, users should use mono_jit_init instead.
1747 * Creates the initial application domain and initializes the mono_defaults
1750 * This function is guaranteed to not run any IL code.
1751 * The runtime is initialized using the provided rutime version.
1753 * Returns: the initial domain.
1756 mono_init_version (const char *domain_name, const char *version)
1758 return mono_init_internal (domain_name, NULL, version);
1764 * Cleans up all metadata modules.
1769 mono_close_exe_image ();
1771 mono_defaults.corlib = NULL;
1773 mono_config_cleanup ();
1774 mono_loader_cleanup ();
1775 mono_classes_cleanup ();
1776 mono_assemblies_cleanup ();
1777 mono_images_cleanup ();
1778 mono_debug_cleanup ();
1779 mono_metadata_cleanup ();
1781 mono_native_tls_free (appdomain_thread_id);
1782 DeleteCriticalSection (&appdomains_mutex);
1790 mono_close_exe_image (void)
1793 mono_image_close (exe_image);
1797 * mono_get_root_domain:
1799 * The root AppDomain is the initial domain created by the runtime when it is
1800 * initialized. Programs execute on this AppDomain, but can create new ones
1801 * later. Currently there is no unmanaged API to create new AppDomains, this
1802 * must be done from managed code.
1804 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1807 mono_get_root_domain (void)
1809 return mono_root_domain;
1815 * Returns: the current domain, to obtain the root domain use
1816 * mono_get_root_domain().
1821 return GET_APPDOMAIN ();
1825 mono_domain_unset (void)
1827 SET_APPDOMAIN (NULL);
1831 mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception)
1833 MonoInternalThread *thread;
1835 if (mono_domain_get () == domain)
1838 SET_APPDOMAIN (domain);
1839 SET_APPCONTEXT (domain->default_context);
1841 if (migrate_exception) {
1842 thread = mono_thread_internal_current ();
1843 if (!thread->abort_exc)
1846 g_assert (thread->abort_exc->object.vtable->domain != domain);
1847 MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
1848 g_assert (thread->abort_exc->object.vtable->domain == domain);
1853 * mono_domain_set_internal:
1854 * @domain: the new domain
1856 * Sets the current domain to @domain.
1859 mono_domain_set_internal (MonoDomain *domain)
1861 mono_domain_set_internal_with_options (domain, TRUE);
1865 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1871 * Create a copy of the data to avoid calling the user callback
1872 * inside the lock because that could lead to deadlocks.
1873 * We can do this because this function is not perf. critical.
1875 mono_appdomains_lock ();
1876 size = appdomain_list_size;
1877 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1878 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1879 mono_appdomains_unlock ();
1881 for (i = 0; i < size; ++i) {
1883 func (copy [i], user_data);
1886 mono_gc_free_fixed (copy);
1890 * mono_domain_assembly_open:
1891 * @domain: the application domain
1892 * @name: file name of the assembly
1894 * fixme: maybe we should integrate this with mono_assembly_open ??
1897 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1899 MonoDomain *current;
1903 mono_domain_assemblies_lock (domain);
1904 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1906 if (strcmp (name, ass->aname.name) == 0) {
1907 mono_domain_assemblies_unlock (domain);
1911 mono_domain_assemblies_unlock (domain);
1913 if (domain != mono_domain_get ()) {
1914 current = mono_domain_get ();
1916 mono_domain_set (domain, FALSE);
1917 ass = mono_assembly_open (name, NULL);
1918 mono_domain_set (current, FALSE);
1920 ass = mono_assembly_open (name, NULL);
1927 unregister_vtable_reflection_type (MonoVTable *vtable)
1929 MonoObject *type = vtable->type;
1931 if (type->vtable->klass != mono_defaults.monotype_class)
1932 MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type);
1936 mono_domain_free (MonoDomain *domain, gboolean force)
1938 int code_size, code_alloc;
1942 if ((domain == mono_root_domain) && !force) {
1943 g_warning ("cant unload root domain");
1947 if (mono_dont_free_domains)
1950 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1952 mono_debug_domain_unload (domain);
1954 mono_appdomains_lock ();
1955 appdomains_list [domain->domain_id] = NULL;
1956 mono_appdomains_unlock ();
1958 /* must do this early as it accesses fields and types */
1959 if (domain->special_static_fields) {
1960 mono_alloc_special_static_data_free (domain->special_static_fields);
1961 g_hash_table_destroy (domain->special_static_fields);
1962 domain->special_static_fields = NULL;
1966 * We must destroy all these hash tables here because they
1967 * contain references to managed objects belonging to the
1968 * domain. Once we let the GC clear the domain there must be
1969 * no more such references, or we'll crash if a collection
1972 mono_g_hash_table_destroy (domain->ldstr_table);
1973 domain->ldstr_table = NULL;
1975 mono_g_hash_table_destroy (domain->env);
1978 if (domain->tlsrec_list) {
1979 mono_thread_destroy_domain_tls (domain);
1980 domain->tlsrec_list = NULL;
1983 mono_reflection_cleanup_domain (domain);
1985 /* This must be done before type_hash is freed */
1986 if (domain->class_vtable_array) {
1988 for (i = 0; i < domain->class_vtable_array->len; ++i)
1989 unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i));
1992 if (domain->type_hash) {
1993 mono_g_hash_table_destroy (domain->type_hash);
1994 domain->type_hash = NULL;
1996 if (domain->type_init_exception_hash) {
1997 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1998 domain->type_init_exception_hash = NULL;
2001 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
2002 MonoAssembly *ass = tmp->data;
2003 mono_assembly_release_gc_roots (ass);
2006 /* Have to zero out reference fields since they will be invalidated by the clear_domain () call below */
2007 for (p = (gpointer*)&domain->MONO_DOMAIN_FIRST_OBJECT; p < (gpointer*)&domain->MONO_DOMAIN_FIRST_GC_TRACKED; ++p)
2010 /* This needs to be done before closing assemblies */
2011 mono_gc_clear_domain (domain);
2013 /* Close dynamic assemblies first, since they have no ref count */
2014 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
2015 MonoAssembly *ass = tmp->data;
2016 if (!ass->image || !ass->image->dynamic)
2018 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);
2019 if (!mono_assembly_close_except_image_pools (ass))
2023 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
2024 MonoAssembly *ass = tmp->data;
2027 if (!ass->image || ass->image->dynamic)
2029 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);
2030 if (!mono_assembly_close_except_image_pools (ass))
2034 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
2035 MonoAssembly *ass = tmp->data;
2037 mono_assembly_close_finish (ass);
2039 g_slist_free (domain->domain_assemblies);
2040 domain->domain_assemblies = NULL;
2043 * Send this after the assemblies have been unloaded and the domain is still in a
2046 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
2048 if (free_domain_hook)
2049 free_domain_hook (domain);
2051 /* FIXME: free delegate_hash_table when it's used */
2052 if (domain->search_path) {
2053 g_strfreev (domain->search_path);
2054 domain->search_path = NULL;
2056 domain->create_proxy_for_type_method = NULL;
2057 domain->private_invoke_method = NULL;
2058 domain->default_context = NULL;
2059 domain->out_of_memory_ex = NULL;
2060 domain->null_reference_ex = NULL;
2061 domain->stack_overflow_ex = NULL;
2062 domain->ephemeron_tombstone = NULL;
2063 domain->entry_assembly = NULL;
2065 g_free (domain->friendly_name);
2066 domain->friendly_name = NULL;
2067 g_ptr_array_free (domain->class_vtable_array, TRUE);
2068 domain->class_vtable_array = NULL;
2069 g_hash_table_destroy (domain->proxy_vtable_hash);
2070 domain->proxy_vtable_hash = NULL;
2071 if (domain->static_data_array) {
2072 mono_gc_free_fixed (domain->static_data_array);
2073 domain->static_data_array = NULL;
2075 mono_internal_hash_table_destroy (&domain->jit_code_hash);
2078 * There might still be jit info tables of this domain which
2079 * are not freed. Since the domain cannot be in use anymore,
2080 * this will free them.
2082 mono_thread_hazardous_try_free_all ();
2083 if (domain->aot_modules)
2084 jit_info_table_free (domain->aot_modules);
2085 g_assert (domain->num_jit_info_tables == 1);
2086 jit_info_table_free (domain->jit_info_table);
2087 domain->jit_info_table = NULL;
2088 g_assert (!domain->jit_info_free_queue);
2090 /* collect statistics */
2091 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
2092 total_domain_code_alloc += code_alloc;
2093 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
2094 max_domain_code_size = MAX (max_domain_code_size, code_size);
2096 if (debug_domain_unload) {
2097 mono_mempool_invalidate (domain->mp);
2098 mono_code_manager_invalidate (domain->code_mp);
2100 #ifndef DISABLE_PERFCOUNTERS
2101 mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
2103 mono_mempool_destroy (domain->mp);
2105 mono_code_manager_destroy (domain->code_mp);
2106 domain->code_mp = NULL;
2108 lock_free_mempool_free (domain->lock_free_mp);
2109 domain->lock_free_mp = NULL;
2111 g_hash_table_destroy (domain->finalizable_objects_hash);
2112 domain->finalizable_objects_hash = NULL;
2113 if (domain->method_rgctx_hash) {
2114 g_hash_table_destroy (domain->method_rgctx_hash);
2115 domain->method_rgctx_hash = NULL;
2117 if (domain->generic_virtual_cases) {
2118 g_hash_table_destroy (domain->generic_virtual_cases);
2119 domain->generic_virtual_cases = NULL;
2121 if (domain->generic_virtual_thunks) {
2122 g_hash_table_destroy (domain->generic_virtual_thunks);
2123 domain->generic_virtual_thunks = NULL;
2125 if (domain->ftnptrs_hash) {
2126 g_hash_table_destroy (domain->ftnptrs_hash);
2127 domain->ftnptrs_hash = NULL;
2130 DeleteCriticalSection (&domain->finalizable_objects_hash_lock);
2131 DeleteCriticalSection (&domain->assemblies_lock);
2132 DeleteCriticalSection (&domain->jit_code_hash_lock);
2133 DeleteCriticalSection (&domain->lock);
2134 domain->setup = NULL;
2136 mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
2138 /* FIXME: anything else required ? */
2140 mono_gc_free_fixed (domain);
2142 #ifndef DISABLE_PERFCOUNTERS
2143 mono_perfcounters->loader_appdomains--;
2146 if (domain == mono_root_domain)
2147 mono_root_domain = NULL;
2151 * mono_domain_get_id:
2154 * Returns: the a domain for a specific domain id.
2157 mono_domain_get_by_id (gint32 domainid)
2159 MonoDomain * domain;
2161 mono_appdomains_lock ();
2162 if (domainid < appdomain_list_size)
2163 domain = appdomains_list [domainid];
2166 mono_appdomains_unlock ();
2172 mono_domain_get_id (MonoDomain *domain)
2174 return domain->domain_id;
2178 * mono_domain_alloc:
2180 * LOCKING: Acquires the domain lock.
2183 mono_domain_alloc (MonoDomain *domain, guint size)
2187 mono_domain_lock (domain);
2188 #ifndef DISABLE_PERFCOUNTERS
2189 mono_perfcounters->loader_bytes += size;
2191 res = mono_mempool_alloc (domain->mp, size);
2192 mono_domain_unlock (domain);
2198 * mono_domain_alloc0:
2200 * LOCKING: Acquires the domain lock.
2203 mono_domain_alloc0 (MonoDomain *domain, guint size)
2207 mono_domain_lock (domain);
2208 #ifndef DISABLE_PERFCOUNTERS
2209 mono_perfcounters->loader_bytes += size;
2211 res = mono_mempool_alloc0 (domain->mp, size);
2212 mono_domain_unlock (domain);
2218 mono_domain_alloc0_lock_free (MonoDomain *domain, guint size)
2220 return lock_free_mempool_alloc0 (domain->lock_free_mp, size);
2224 * mono_domain_code_reserve:
2226 * LOCKING: Acquires the domain lock.
2229 mono_domain_code_reserve (MonoDomain *domain, int size)
2233 mono_domain_lock (domain);
2234 res = mono_code_manager_reserve (domain->code_mp, size);
2235 mono_domain_unlock (domain);
2241 * mono_domain_code_reserve_align:
2243 * LOCKING: Acquires the domain lock.
2246 mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment)
2250 mono_domain_lock (domain);
2251 res = mono_code_manager_reserve_align (domain->code_mp, size, alignment);
2252 mono_domain_unlock (domain);
2258 * mono_domain_code_commit:
2260 * LOCKING: Acquires the domain lock.
2263 mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize)
2265 mono_domain_lock (domain);
2266 mono_code_manager_commit (domain->code_mp, data, size, newsize);
2267 mono_domain_unlock (domain);
2270 #if defined(__native_client_codegen__) && defined(__native_client__)
2272 * Given the temporary buffer (allocated by mono_domain_code_reserve) into which
2273 * we are generating code, return a pointer to the destination in the dynamic
2274 * code segment into which the code will be copied when mono_domain_code_commit
2276 * LOCKING: Acquires the domain lock.
2279 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2282 mono_domain_lock (domain);
2283 dest = nacl_code_manager_get_code_dest (domain->code_mp, data);
2284 mono_domain_unlock (domain);
2289 * Convenience function which calls mono_domain_code_commit to validate and copy
2290 * the code. The caller sets *buf_base and *buf_size to the start and size of
2291 * the buffer (allocated by mono_domain_code_reserve), and *code_end to the byte
2292 * after the last instruction byte. On return, *buf_base will point to the start
2293 * of the copied in the code segment, and *code_end will point after the end of
2297 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2299 guint8 *tmp = nacl_domain_get_code_dest (domain, *buf_base);
2300 mono_domain_code_commit (domain, *buf_base, buf_size, *code_end - *buf_base);
2301 *code_end = tmp + (*code_end - *buf_base);
2307 /* no-op versions of Native Client functions */
2310 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2316 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2323 * mono_domain_code_foreach:
2324 * Iterate over the code thunks of the code manager of @domain.
2326 * The @func callback MUST not take any locks. If it really needs to, it must respect
2327 * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety
2328 * LOCKING: Acquires the domain lock.
2332 mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data)
2334 mono_domain_lock (domain);
2335 mono_code_manager_foreach (domain->code_mp, func, user_data);
2336 mono_domain_unlock (domain);
2341 mono_context_set (MonoAppContext * new_context)
2343 SET_APPCONTEXT (new_context);
2347 mono_context_get (void)
2349 return GET_APPCONTEXT ();
2352 /* LOCKING: the caller holds the lock for this domain */
2354 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
2356 /* The first entry in the array is the index of the next free slot
2357 * and the total size of the array
2360 if (domain->static_data_array) {
2361 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
2362 next = GPOINTER_TO_INT (domain->static_data_array [0]);
2364 /* 'data' is allocated by alloc_fixed */
2365 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2));
2366 mono_gc_memmove_aligned (new_array, domain->static_data_array, sizeof (gpointer) * size);
2368 new_array [1] = GINT_TO_POINTER (size);
2369 mono_gc_free_fixed (domain->static_data_array);
2370 domain->static_data_array = new_array;
2374 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, MONO_GC_ROOT_DESCR_FOR_FIXED (size));
2376 new_array [0] = GINT_TO_POINTER (next);
2377 new_array [1] = GINT_TO_POINTER (size);
2378 domain->static_data_array = new_array;
2380 domain->static_data_array [next++] = data;
2381 domain->static_data_array [0] = GINT_TO_POINTER (next);
2385 mono_get_corlib (void)
2387 return mono_defaults.corlib;
2391 mono_get_object_class (void)
2393 return mono_defaults.object_class;
2397 mono_get_byte_class (void)
2399 return mono_defaults.byte_class;
2403 mono_get_void_class (void)
2405 return mono_defaults.void_class;
2409 mono_get_boolean_class (void)
2411 return mono_defaults.boolean_class;
2415 mono_get_sbyte_class (void)
2417 return mono_defaults.sbyte_class;
2421 mono_get_int16_class (void)
2423 return mono_defaults.int16_class;
2427 mono_get_uint16_class (void)
2429 return mono_defaults.uint16_class;
2433 mono_get_int32_class (void)
2435 return mono_defaults.int32_class;
2439 mono_get_uint32_class (void)
2441 return mono_defaults.uint32_class;
2445 mono_get_intptr_class (void)
2447 return mono_defaults.int_class;
2451 mono_get_uintptr_class (void)
2453 return mono_defaults.uint_class;
2457 mono_get_int64_class (void)
2459 return mono_defaults.int64_class;
2463 mono_get_uint64_class (void)
2465 return mono_defaults.uint64_class;
2469 mono_get_single_class (void)
2471 return mono_defaults.single_class;
2475 mono_get_double_class (void)
2477 return mono_defaults.double_class;
2481 mono_get_char_class (void)
2483 return mono_defaults.char_class;
2487 mono_get_string_class (void)
2489 return mono_defaults.string_class;
2493 mono_get_enum_class (void)
2495 return mono_defaults.enum_class;
2499 mono_get_array_class (void)
2501 return mono_defaults.array_class;
2505 mono_get_thread_class (void)
2507 return mono_defaults.thread_class;
2511 mono_get_exception_class (void)
2513 return mono_defaults.exception_class;
2517 static char* get_attribute_value (const gchar **attribute_names,
2518 const gchar **attribute_values,
2519 const char *att_name)
2522 for (n=0; attribute_names[n] != NULL; n++) {
2523 if (strcmp (attribute_names[n], att_name) == 0)
2524 return g_strdup (attribute_values[n]);
2529 static void start_element (GMarkupParseContext *context,
2530 const gchar *element_name,
2531 const gchar **attribute_names,
2532 const gchar **attribute_values,
2536 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2538 if (strcmp (element_name, "configuration") == 0) {
2539 app_config->configuration_count++;
2542 if (strcmp (element_name, "startup") == 0) {
2543 app_config->startup_count++;
2547 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2550 if (strcmp (element_name, "requiredRuntime") == 0) {
2551 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2552 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2553 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2554 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2558 static void end_element (GMarkupParseContext *context,
2559 const gchar *element_name,
2563 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2565 if (strcmp (element_name, "configuration") == 0) {
2566 app_config->configuration_count--;
2567 } else if (strcmp (element_name, "startup") == 0) {
2568 app_config->startup_count--;
2572 static const GMarkupParser
2581 static AppConfigInfo *
2582 app_config_parse (const char *exe_filename)
2584 AppConfigInfo *app_config;
2585 GMarkupParseContext *context;
2588 const char *bundled_config;
2589 char *config_filename;
2591 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2593 if (bundled_config) {
2594 text = g_strdup (bundled_config);
2595 len = strlen (text);
2597 config_filename = g_strconcat (exe_filename, ".config", NULL);
2599 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2600 g_free (config_filename);
2603 g_free (config_filename);
2606 app_config = g_new0 (AppConfigInfo, 1);
2608 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2609 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2610 g_markup_parse_context_end_parse (context, NULL);
2612 g_markup_parse_context_free (context);
2618 app_config_free (AppConfigInfo* app_config)
2621 GSList *list = app_config->supported_runtimes;
2622 while (list != NULL) {
2623 rt = (char*)list->data;
2625 list = g_slist_next (list);
2627 g_slist_free (app_config->supported_runtimes);
2628 g_free (app_config->required_runtime);
2629 g_free (app_config);
2633 static const MonoRuntimeInfo*
2634 get_runtime_by_version (const char *version)
2637 int max = G_N_ELEMENTS (supported_runtimes);
2643 for (n=0; n<max; n++) {
2644 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2645 return &supported_runtimes[n];
2648 vlen = strlen (version);
2649 if (vlen >= 4 && version [1] - '0' >= 4) {
2650 for (n=0; n<max; n++) {
2651 if (strncmp (version, supported_runtimes[n].runtime_version, 4) == 0)
2652 return &supported_runtimes[n];
2660 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2662 AppConfigInfo* app_config;
2664 const MonoRuntimeInfo* runtime = NULL;
2665 MonoImage *image = NULL;
2667 app_config = app_config_parse (exe_file);
2669 if (app_config != NULL) {
2670 /* Check supportedRuntime elements, if none is supported, fail.
2671 * If there are no such elements, look for a requiredRuntime element.
2673 if (app_config->supported_runtimes != NULL) {
2675 GSList *list = app_config->supported_runtimes;
2676 while (list != NULL) {
2677 version = (char*) list->data;
2678 runtime = get_runtime_by_version (version);
2679 if (runtime != NULL)
2680 runtimes [n++] = runtime;
2681 list = g_slist_next (list);
2683 runtimes [n] = NULL;
2684 app_config_free (app_config);
2688 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2689 if (app_config->required_runtime != NULL) {
2690 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2691 runtimes [1] = NULL;
2692 app_config_free (app_config);
2695 app_config_free (app_config);
2698 /* Look for a runtime with the exact version */
2699 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2702 image = mono_image_open (exe_file, NULL);
2704 if (image == NULL) {
2705 /* The image is wrong or the file was not found. In this case return
2706 * a default runtime and leave to the initialization method the work of
2707 * reporting the error.
2709 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2710 runtimes [1] = NULL;
2716 runtimes [0] = get_runtime_by_version (image->version);
2717 runtimes [1] = NULL;
2722 * mono_get_runtime_info:
2724 * Returns: the version of the current runtime instance.
2726 const MonoRuntimeInfo*
2727 mono_get_runtime_info (void)
2729 return current_runtime;
2733 mono_debugger_check_runtime_version (const char *filename)
2735 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2736 const MonoRuntimeInfo *rinfo;
2739 get_runtimes_from_exe (filename, &image, runtimes);
2740 rinfo = runtimes [0];
2743 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2745 if (rinfo != current_runtime)
2746 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2747 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2748 filename, rinfo->runtime_version);
2754 * mono_framework_version:
2756 * Return the major version of the framework curently executing.
2759 mono_framework_version (void)
2761 return current_runtime->framework_version [0] - '0';
2765 mono_enable_debug_domain_unload (gboolean enable)
2767 debug_domain_unload = enable;