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}, {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 {"moonlight", "2.1", { {2,0,5,0}, { 9,0,0,0}, {3,5,0,0}, {3,0,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;
466 if (num_chunks == 0) {
467 g_assert (num_elements == 0);
468 return jit_info_table_new (old->domain);
470 g_assert (num_chunks > 0);
472 new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
473 new->domain = old->domain;
474 new->num_chunks = num_chunks;
476 for (i = 0; i < num_chunks; ++i)
477 new->chunks [i] = jit_info_table_new_chunk ();
481 for (i = 0; i < old->num_chunks; ++i) {
482 MonoJitInfoTableChunk *chunk = old->chunks [i];
483 int chunk_num_elements = chunk->num_elements;
486 for (j = 0; j < chunk_num_elements; ++j) {
487 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
488 g_assert (new_chunk < num_chunks);
489 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
490 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
491 new->chunks [new_chunk]->num_elements = new_element;
499 if (new_chunk < num_chunks) {
500 g_assert (new_chunk == num_chunks - 1);
501 new->chunks [new_chunk]->num_elements = new_element;
502 g_assert (new->chunks [new_chunk]->num_elements > 0);
505 for (i = 0; i < num_chunks; ++i) {
506 MonoJitInfoTableChunk *chunk = new->chunks [i];
507 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
509 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
516 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
518 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
519 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
521 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
523 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
524 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
526 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
527 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
529 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
530 + new1->data [new1->num_elements - 1]->code_size;
531 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
532 + new2->data [new2->num_elements - 1]->code_size;
538 static MonoJitInfoTable*
539 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
541 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
542 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
545 new_table->domain = table->domain;
546 new_table->num_chunks = table->num_chunks + 1;
549 for (i = 0; i < table->num_chunks; ++i) {
550 if (table->chunks [i] == chunk) {
551 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
554 new_table->chunks [j] = table->chunks [i];
555 ++new_table->chunks [j]->refcount;
560 g_assert (j == new_table->num_chunks);
565 static MonoJitInfoTableChunk*
566 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
568 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
572 for (i = 0; i < old->num_elements; ++i) {
573 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
574 new->data [j++] = old->data [i];
577 new->num_elements = j;
578 if (new->num_elements > 0)
579 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
581 new->last_code_end = old->last_code_end;
586 static MonoJitInfoTable*
587 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
589 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
590 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
593 new_table->domain = table->domain;
594 new_table->num_chunks = table->num_chunks;
597 for (i = 0; i < table->num_chunks; ++i) {
598 if (table->chunks [i] == chunk)
599 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
601 new_table->chunks [j] = table->chunks [i];
602 ++new_table->chunks [j]->refcount;
607 g_assert (j == new_table->num_chunks);
612 /* As we add an element to the table the case can arise that the chunk
613 * to which we need to add is already full. In that case we have to
614 * allocate a new table and do something about that chunk. We have
615 * several strategies:
617 * If the number of elements in the table is below the low watermark
618 * or above the high watermark, we reallocate the whole table.
619 * Otherwise we only concern ourselves with the overflowing chunk:
621 * If there are no tombstones in the chunk then we split the chunk in
622 * two, each half full.
624 * If the chunk does contain tombstones, we just make a new copy of
625 * the chunk without the tombstones, which will have room for at least
626 * the one element we have to add.
628 static MonoJitInfoTable*
629 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
631 int num_elements = jit_info_table_num_elements (table);
634 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
635 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
636 //printf ("reallocing table\n");
637 return jit_info_table_realloc (table);
640 /* count the number of non-tombstone elements in the chunk */
642 for (i = 0; i < chunk->num_elements; ++i) {
643 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
647 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
648 //printf ("splitting chunk\n");
649 return jit_info_table_copy_and_split_chunk (table, chunk);
652 //printf ("purifying chunk\n");
653 return jit_info_table_copy_and_purify_chunk (table, chunk);
656 /* We add elements to the table by first making space for them by
657 * shifting the elements at the back to the right, one at a time.
658 * This results in duplicate entries during the process, but during
659 * all the time the table is in a sorted state. Also, when an element
660 * is replaced by another one, the element that replaces it has an end
661 * address that is equal to or lower than that of the replaced
662 * element. That property is necessary to guarantee that when
663 * searching for an element we end up at a position not higher than
664 * the one we're looking for (i.e. we either find the element directly
665 * or we end up to the left of it).
668 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
670 MonoJitInfoTable *table;
672 MonoJitInfoTableChunk *chunk;
676 g_assert (ji->method != NULL);
678 mono_domain_lock (domain);
680 ++mono_stats.jit_info_table_insert_count;
682 table = domain->jit_info_table;
685 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
686 g_assert (chunk_pos < table->num_chunks);
687 chunk = table->chunks [chunk_pos];
689 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
690 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
692 /* Debugging code, should be removed. */
693 //jit_info_table_check (new_table);
695 domain->jit_info_table = new_table;
696 mono_memory_barrier ();
697 domain->num_jit_info_tables++;
698 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free, TRUE, FALSE);
704 /* Debugging code, should be removed. */
705 //jit_info_table_check (table);
707 num_elements = chunk->num_elements;
709 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
711 /* First we need to size up the chunk by one, by copying the
712 last item, or inserting the first one, if the table is
714 if (num_elements > 0)
715 chunk->data [num_elements] = chunk->data [num_elements - 1];
717 chunk->data [0] = ji;
718 mono_memory_write_barrier ();
719 chunk->num_elements = ++num_elements;
721 /* Shift the elements up one by one. */
722 for (i = num_elements - 2; i >= pos; --i) {
723 mono_memory_write_barrier ();
724 chunk->data [i + 1] = chunk->data [i];
727 /* Now we have room and can insert the new item. */
728 mono_memory_write_barrier ();
729 chunk->data [pos] = ji;
731 /* Set the high code end address chunk entry. */
732 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
733 + chunk->data [chunk->num_elements - 1]->code_size;
735 /* Debugging code, should be removed. */
736 //jit_info_table_check (table);
738 mono_domain_unlock (domain);
742 mono_jit_info_make_tombstone (MonoJitInfo *ji)
744 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
746 tombstone->code_start = ji->code_start;
747 tombstone->code_size = ji->code_size;
748 tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
754 * LOCKING: domain lock
757 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
759 if (domain->num_jit_info_tables <= 1) {
760 /* Can it actually happen that we only have one table
761 but ji is still hazardous? */
762 mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
764 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
769 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
771 MonoJitInfoTable *table;
772 MonoJitInfoTableChunk *chunk;
773 gpointer start = ji->code_start;
776 mono_domain_lock (domain);
777 table = domain->jit_info_table;
779 ++mono_stats.jit_info_table_remove_count;
781 chunk_pos = jit_info_table_index (table, start);
782 g_assert (chunk_pos < table->num_chunks);
784 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
787 chunk = table->chunks [chunk_pos];
789 while (pos < chunk->num_elements) {
790 if (chunk->data [pos] == ji)
793 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
794 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
795 <= (guint8*)ji->code_start + ji->code_size);
802 } while (chunk_pos < table->num_chunks);
805 g_assert (chunk->data [pos] == ji);
807 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
809 /* Debugging code, should be removed. */
810 //jit_info_table_check (table);
812 mono_jit_info_free_or_queue (domain, ji);
814 mono_domain_unlock (domain);
817 static MonoAotModuleInfoTable*
818 mono_aot_module_info_table_new (void)
820 return g_array_new (FALSE, FALSE, sizeof (gpointer));
824 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
826 int left = 0, right = table->len;
828 while (left < right) {
829 int pos = (left + right) / 2;
830 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
831 char *start = ainfo->start;
832 char *end = ainfo->end;
836 else if (addr >= end)
846 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
848 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
851 ainfo->image = image;
852 ainfo->start = start;
855 mono_appdomains_lock ();
858 aot_modules = mono_aot_module_info_table_new ();
860 pos = aot_info_table_index (aot_modules, start);
862 g_array_insert_val (aot_modules, pos, ainfo);
864 mono_appdomains_unlock ();
868 mono_jit_info_find_aot_module (guint8* addr)
870 guint left = 0, right;
875 mono_appdomains_lock ();
877 right = aot_modules->len;
878 while (left < right) {
879 guint pos = (left + right) / 2;
880 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
882 if (addr < (guint8*)ai->start)
884 else if (addr >= (guint8*)ai->end)
887 mono_appdomains_unlock ();
892 mono_appdomains_unlock ();
898 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
900 jit_info_find_in_aot_func = func;
904 mono_jit_info_get_code_start (MonoJitInfo* ji)
906 return ji->code_start;
910 mono_jit_info_get_code_size (MonoJitInfo* ji)
912 return ji->code_size;
916 mono_jit_info_get_method (MonoJitInfo* ji)
922 jit_info_key_extract (gpointer value)
924 MonoJitInfo *info = (MonoJitInfo*)value;
930 jit_info_next_value (gpointer value)
932 MonoJitInfo *info = (MonoJitInfo*)value;
934 return (gpointer*)&info->next_jit_code_hash;
938 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
940 mono_internal_hash_table_init (jit_code_hash,
941 mono_aligned_addr_hash,
942 jit_info_key_extract,
943 jit_info_next_value);
947 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
949 if (ji->has_generic_jit_info)
950 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
956 * mono_jit_info_get_generic_sharing_context:
959 * Returns the jit info's generic sharing context, or NULL if it
962 MonoGenericSharingContext*
963 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
965 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
968 return gi->generic_sharing_context;
974 * mono_jit_info_set_generic_sharing_context:
976 * @gsctx: a generic sharing context
978 * Sets the jit info's generic sharing context. The jit info must
979 * have memory allocated for the context.
982 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
984 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
988 gi->generic_sharing_context = gsctx;
991 MonoTryBlockHoleTableJitInfo*
992 mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
994 if (ji->has_try_block_holes) {
995 char *ptr = (char*)&ji->clauses [ji->num_clauses];
996 if (ji->has_generic_jit_info)
997 ptr += sizeof (MonoGenericJitInfo);
998 return (MonoTryBlockHoleTableJitInfo*)ptr;
1005 mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
1007 if (ji->has_arch_eh_info) {
1008 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1009 if (ji->has_generic_jit_info)
1010 ptr += sizeof (MonoGenericJitInfo);
1011 if (ji->has_try_block_holes)
1012 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
1013 return (MonoArchEHJitInfo*)ptr;
1020 mono_jit_info_get_cas_info (MonoJitInfo *ji)
1022 if (ji->has_cas_info) {
1023 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1024 if (ji->has_generic_jit_info)
1025 ptr += sizeof (MonoGenericJitInfo);
1026 if (ji->has_try_block_holes)
1027 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
1028 if (ji->has_arch_eh_info)
1029 ptr += sizeof (MonoArchEHJitInfo);
1030 return (MonoMethodCasInfo*)ptr;
1037 mono_install_create_domain_hook (MonoCreateDomainFunc func)
1039 create_domain_hook = func;
1043 mono_install_free_domain_hook (MonoFreeDomainFunc func)
1045 free_domain_hook = func;
1049 * mono_string_equal:
1050 * @s1: First string to compare
1051 * @s2: Second string to compare
1053 * Returns FALSE if the strings differ.
1056 mono_string_equal (MonoString *s1, MonoString *s2)
1058 int l1 = mono_string_length (s1);
1059 int l2 = mono_string_length (s2);
1066 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
1071 * @s: the string to hash
1073 * Returns the hash for the string.
1076 mono_string_hash (MonoString *s)
1078 const guint16 *p = mono_string_chars (s);
1079 int i, len = mono_string_length (s);
1082 for (i = 0; i < len; i++) {
1083 h = (h << 5) - h + *p;
1091 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1093 int len = GPOINTER_TO_INT (s1 [0]);
1094 if (len != GPOINTER_TO_INT (s2 [0]))
1097 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1101 mono_ptrarray_hash (gpointer *s)
1104 int len = GPOINTER_TO_INT (s [0]);
1107 for (i = 1; i < len; i++)
1108 hash += GPOINTER_TO_UINT (s [i]);
1114 * Allocate an id for domain and set domain->domain_id.
1115 * LOCKING: must be called while holding appdomains_mutex.
1116 * We try to assign low numbers to the domain, so it can be used
1117 * as an index in data tables to lookup domain-specific info
1118 * with minimal memory overhead. We also try not to reuse the
1119 * same id too quickly (to help debugging).
1122 domain_id_alloc (MonoDomain *domain)
1125 if (!appdomains_list) {
1126 appdomain_list_size = 2;
1127 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1129 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1130 if (!appdomains_list [i]) {
1136 for (i = 0; i < appdomain_next; ++i) {
1137 if (!appdomains_list [i]) {
1144 MonoDomain **new_list;
1145 int new_size = appdomain_list_size * 2;
1146 if (new_size >= (1 << 16))
1147 g_assert_not_reached ();
1148 id = appdomain_list_size;
1149 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1150 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1151 mono_gc_free_fixed (appdomains_list);
1152 appdomains_list = new_list;
1153 appdomain_list_size = new_size;
1155 domain->domain_id = id;
1156 appdomains_list [id] = domain;
1158 if (appdomain_next > appdomain_list_size)
1163 static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1164 static gpointer domain_gc_desc = NULL;
1165 static guint32 domain_shadow_serial = 0L;
1168 mono_domain_create (void)
1171 guint32 shadow_serial;
1173 mono_appdomains_lock ();
1174 shadow_serial = domain_shadow_serial++;
1176 if (!domain_gc_desc) {
1177 unsigned int i, bit = 0;
1178 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1179 bit = i / sizeof (gpointer);
1180 domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32);
1182 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1184 mono_appdomains_unlock ();
1186 #ifdef HAVE_BOEHM_GC
1188 * Boehm doesn't like roots inside GC allocated objects, and alloc_fixed returns
1189 * a GC_MALLOC-ed object, contrary to the api docs. This causes random crashes when
1190 * running the corlib test suite.
1191 * To solve this, we pass a NULL descriptor, and don't register roots.
1193 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL);
1195 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1196 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);
1198 domain->shadow_serial = shadow_serial;
1199 domain->domain = NULL;
1200 domain->setup = NULL;
1201 domain->friendly_name = NULL;
1202 domain->search_path = NULL;
1204 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1206 domain->mp = mono_mempool_new ();
1207 domain->code_mp = mono_code_manager_new ();
1208 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1209 domain->domain_assemblies = NULL;
1210 domain->assembly_bindings = NULL;
1211 domain->assembly_bindings_parsed = FALSE;
1212 domain->class_vtable_array = g_ptr_array_new ();
1213 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1214 domain->static_data_array = NULL;
1215 mono_jit_code_hash_init (&domain->jit_code_hash);
1216 domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1217 domain->num_jit_info_tables = 1;
1218 domain->jit_info_table = jit_info_table_new (domain);
1219 domain->jit_info_free_queue = NULL;
1220 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1221 domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1223 InitializeCriticalSection (&domain->lock);
1224 InitializeCriticalSection (&domain->assemblies_lock);
1225 InitializeCriticalSection (&domain->jit_code_hash_lock);
1226 InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
1228 domain->method_rgctx_hash = NULL;
1230 mono_appdomains_lock ();
1231 domain_id_alloc (domain);
1232 mono_appdomains_unlock ();
1234 #ifndef DISABLE_PERFCOUNTERS
1235 mono_perfcounters->loader_appdomains++;
1236 mono_perfcounters->loader_total_appdomains++;
1239 mono_debug_domain_create (domain);
1241 if (create_domain_hook)
1242 create_domain_hook (domain);
1244 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1250 * mono_init_internal:
1252 * Creates the initial application domain and initializes the mono_defaults
1254 * This function is guaranteed to not run any IL code.
1255 * If exe_filename is not NULL, the method will determine the required runtime
1256 * from the exe configuration file or the version PE field.
1257 * If runtime_version is not NULL, that runtime version will be used.
1258 * Either exe_filename or runtime_version must be provided.
1260 * Returns: the initial domain.
1263 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1265 static MonoDomain *domain = NULL;
1266 MonoAssembly *ass = NULL;
1267 MonoImageOpenStatus status = MONO_IMAGE_OK;
1268 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1272 g_assert_not_reached ();
1275 /* Avoid system error message boxes. */
1276 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1283 #ifndef DISABLE_PERFCOUNTERS
1284 mono_perfcounters_init ();
1287 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1288 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1289 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1291 mono_gc_base_init ();
1293 MONO_FAST_TLS_INIT (tls_appdomain);
1294 mono_native_tls_alloc (&appdomain_thread_id, NULL);
1296 InitializeCriticalSection (&appdomains_mutex);
1298 mono_metadata_init ();
1299 mono_images_init ();
1300 mono_assemblies_init ();
1301 mono_classes_init ();
1302 mono_loader_init ();
1303 mono_reflection_init ();
1305 /* FIXME: When should we release this memory? */
1306 MONO_GC_REGISTER_ROOT_FIXED (appdomains_list);
1308 domain = mono_domain_create ();
1309 mono_root_domain = domain;
1311 SET_APPDOMAIN (domain);
1313 /* Get a list of runtimes supported by the exe */
1314 if (exe_filename != NULL) {
1316 * This function will load the exe file as a MonoImage. We need to close it, but
1317 * that would mean it would be reloaded later. So instead, we save it to
1318 * exe_image, and close it during shutdown.
1320 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1323 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1325 exe_image = mono_image_open (exe_filename, NULL);
1327 mono_fixup_exe_image (exe_image);
1329 } else if (runtime_version != NULL) {
1330 runtimes [0] = get_runtime_by_version (runtime_version);
1331 runtimes [1] = NULL;
1334 if (runtimes [0] == NULL) {
1335 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1336 runtimes [0] = default_runtime;
1337 runtimes [1] = NULL;
1338 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1339 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1342 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1343 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1344 current_runtime = runtimes [n];
1345 ass = mono_assembly_load_corlib (current_runtime, &status);
1346 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1351 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1353 case MONO_IMAGE_ERROR_ERRNO: {
1354 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1355 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1356 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1357 g_free (corlib_file);
1360 case MONO_IMAGE_IMAGE_INVALID:
1361 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1362 mono_assembly_getrootdir ());
1364 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1365 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1366 mono_assembly_getrootdir ());
1369 /* to suppress compiler warning */
1375 mono_defaults.corlib = mono_assembly_get_image (ass);
1377 mono_defaults.object_class = mono_class_from_name (
1378 mono_defaults.corlib, "System", "Object");
1379 g_assert (mono_defaults.object_class != 0);
1381 mono_defaults.void_class = mono_class_from_name (
1382 mono_defaults.corlib, "System", "Void");
1383 g_assert (mono_defaults.void_class != 0);
1385 mono_defaults.boolean_class = mono_class_from_name (
1386 mono_defaults.corlib, "System", "Boolean");
1387 g_assert (mono_defaults.boolean_class != 0);
1389 mono_defaults.byte_class = mono_class_from_name (
1390 mono_defaults.corlib, "System", "Byte");
1391 g_assert (mono_defaults.byte_class != 0);
1393 mono_defaults.sbyte_class = mono_class_from_name (
1394 mono_defaults.corlib, "System", "SByte");
1395 g_assert (mono_defaults.sbyte_class != 0);
1397 mono_defaults.int16_class = mono_class_from_name (
1398 mono_defaults.corlib, "System", "Int16");
1399 g_assert (mono_defaults.int16_class != 0);
1401 mono_defaults.uint16_class = mono_class_from_name (
1402 mono_defaults.corlib, "System", "UInt16");
1403 g_assert (mono_defaults.uint16_class != 0);
1405 mono_defaults.int32_class = mono_class_from_name (
1406 mono_defaults.corlib, "System", "Int32");
1407 g_assert (mono_defaults.int32_class != 0);
1409 mono_defaults.uint32_class = mono_class_from_name (
1410 mono_defaults.corlib, "System", "UInt32");
1411 g_assert (mono_defaults.uint32_class != 0);
1413 mono_defaults.uint_class = mono_class_from_name (
1414 mono_defaults.corlib, "System", "UIntPtr");
1415 g_assert (mono_defaults.uint_class != 0);
1417 mono_defaults.int_class = mono_class_from_name (
1418 mono_defaults.corlib, "System", "IntPtr");
1419 g_assert (mono_defaults.int_class != 0);
1421 mono_defaults.int64_class = mono_class_from_name (
1422 mono_defaults.corlib, "System", "Int64");
1423 g_assert (mono_defaults.int64_class != 0);
1425 mono_defaults.uint64_class = mono_class_from_name (
1426 mono_defaults.corlib, "System", "UInt64");
1427 g_assert (mono_defaults.uint64_class != 0);
1429 mono_defaults.single_class = mono_class_from_name (
1430 mono_defaults.corlib, "System", "Single");
1431 g_assert (mono_defaults.single_class != 0);
1433 mono_defaults.double_class = mono_class_from_name (
1434 mono_defaults.corlib, "System", "Double");
1435 g_assert (mono_defaults.double_class != 0);
1437 mono_defaults.char_class = mono_class_from_name (
1438 mono_defaults.corlib, "System", "Char");
1439 g_assert (mono_defaults.char_class != 0);
1441 mono_defaults.string_class = mono_class_from_name (
1442 mono_defaults.corlib, "System", "String");
1443 g_assert (mono_defaults.string_class != 0);
1445 mono_defaults.enum_class = mono_class_from_name (
1446 mono_defaults.corlib, "System", "Enum");
1447 g_assert (mono_defaults.enum_class != 0);
1449 mono_defaults.array_class = mono_class_from_name (
1450 mono_defaults.corlib, "System", "Array");
1451 g_assert (mono_defaults.array_class != 0);
1453 mono_defaults.delegate_class = mono_class_from_name (
1454 mono_defaults.corlib, "System", "Delegate");
1455 g_assert (mono_defaults.delegate_class != 0 );
1457 mono_defaults.multicastdelegate_class = mono_class_from_name (
1458 mono_defaults.corlib, "System", "MulticastDelegate");
1459 g_assert (mono_defaults.multicastdelegate_class != 0 );
1461 mono_defaults.asyncresult_class = mono_class_from_name (
1462 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1464 g_assert (mono_defaults.asyncresult_class != 0 );
1466 mono_defaults.manualresetevent_class = mono_class_from_name (
1467 mono_defaults.corlib, "System.Threading", "ManualResetEvent");
1468 g_assert (mono_defaults.manualresetevent_class != 0 );
1470 mono_defaults.typehandle_class = mono_class_from_name (
1471 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1472 g_assert (mono_defaults.typehandle_class != 0);
1474 mono_defaults.methodhandle_class = mono_class_from_name (
1475 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1476 g_assert (mono_defaults.methodhandle_class != 0);
1478 mono_defaults.fieldhandle_class = mono_class_from_name (
1479 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1480 g_assert (mono_defaults.fieldhandle_class != 0);
1482 mono_defaults.systemtype_class = mono_class_from_name (
1483 mono_defaults.corlib, "System", "Type");
1484 g_assert (mono_defaults.systemtype_class != 0);
1486 mono_defaults.monotype_class = mono_class_from_name (
1487 mono_defaults.corlib, "System", "MonoType");
1488 g_assert (mono_defaults.monotype_class != 0);
1490 mono_defaults.exception_class = mono_class_from_name (
1491 mono_defaults.corlib, "System", "Exception");
1492 g_assert (mono_defaults.exception_class != 0);
1494 mono_defaults.threadabortexception_class = mono_class_from_name (
1495 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1496 g_assert (mono_defaults.threadabortexception_class != 0);
1498 mono_defaults.thread_class = mono_class_from_name (
1499 mono_defaults.corlib, "System.Threading", "Thread");
1500 g_assert (mono_defaults.thread_class != 0);
1502 mono_defaults.internal_thread_class = mono_class_from_name (
1503 mono_defaults.corlib, "System.Threading", "InternalThread");
1504 if (!mono_defaults.internal_thread_class) {
1505 /* This can happen with an old mscorlib */
1506 fprintf (stderr, "Corlib too old for this runtime.\n");
1507 fprintf (stderr, "Loaded from: %s\n",
1508 mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown");
1512 mono_defaults.appdomain_class = mono_class_from_name (
1513 mono_defaults.corlib, "System", "AppDomain");
1514 g_assert (mono_defaults.appdomain_class != 0);
1516 mono_defaults.transparent_proxy_class = mono_class_from_name (
1517 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1518 g_assert (mono_defaults.transparent_proxy_class != 0);
1520 mono_defaults.real_proxy_class = mono_class_from_name (
1521 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1522 g_assert (mono_defaults.real_proxy_class != 0);
1524 mono_defaults.mono_method_message_class = mono_class_from_name (
1525 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1526 g_assert (mono_defaults.mono_method_message_class != 0);
1528 mono_defaults.field_info_class = mono_class_from_name (
1529 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1530 g_assert (mono_defaults.field_info_class != 0);
1532 mono_defaults.method_info_class = mono_class_from_name (
1533 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1534 g_assert (mono_defaults.method_info_class != 0);
1536 mono_defaults.stringbuilder_class = mono_class_from_name (
1537 mono_defaults.corlib, "System.Text", "StringBuilder");
1538 g_assert (mono_defaults.stringbuilder_class != 0);
1540 mono_defaults.math_class = mono_class_from_name (
1541 mono_defaults.corlib, "System", "Math");
1542 g_assert (mono_defaults.math_class != 0);
1544 mono_defaults.stack_frame_class = mono_class_from_name (
1545 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1546 g_assert (mono_defaults.stack_frame_class != 0);
1548 mono_defaults.stack_trace_class = mono_class_from_name (
1549 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1550 g_assert (mono_defaults.stack_trace_class != 0);
1552 mono_defaults.marshal_class = mono_class_from_name (
1553 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1554 g_assert (mono_defaults.marshal_class != 0);
1556 mono_defaults.iserializeable_class = mono_class_from_name (
1557 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1558 g_assert (mono_defaults.iserializeable_class != 0);
1560 mono_defaults.serializationinfo_class = mono_class_from_name (
1561 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1562 g_assert (mono_defaults.serializationinfo_class != 0);
1564 mono_defaults.streamingcontext_class = mono_class_from_name (
1565 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1566 g_assert (mono_defaults.streamingcontext_class != 0);
1568 mono_defaults.typed_reference_class = mono_class_from_name (
1569 mono_defaults.corlib, "System", "TypedReference");
1570 g_assert (mono_defaults.typed_reference_class != 0);
1572 mono_defaults.argumenthandle_class = mono_class_from_name (
1573 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1574 g_assert (mono_defaults.argumenthandle_class != 0);
1576 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1577 mono_defaults.corlib, "System", "MarshalByRefObject");
1578 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1580 mono_defaults.monitor_class = mono_class_from_name (
1581 mono_defaults.corlib, "System.Threading", "Monitor");
1582 g_assert (mono_defaults.monitor_class != 0);
1584 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1585 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1586 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1588 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1589 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1591 mono_defaults.executioncontext_class = mono_class_from_name (
1592 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1594 mono_defaults.internals_visible_class = mono_class_from_name (
1595 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1597 mono_defaults.critical_finalizer_object = mono_class_from_name (
1598 mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
1601 * mscorlib needs a little help, only now it can load its friends list (after we have
1602 * loaded the InternalsVisibleToAttribute), load it now
1604 mono_assembly_load_friends (ass);
1606 mono_defaults.safehandle_class = mono_class_from_name (
1607 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1609 mono_defaults.handleref_class = mono_class_from_name (
1610 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1612 mono_defaults.attribute_class = mono_class_from_name (
1613 mono_defaults.corlib, "System", "Attribute");
1615 mono_defaults.customattribute_data_class = mono_class_from_name (
1616 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1618 /* these are initialized lazily when COM features are used */
1620 mono_defaults.variant_class = NULL;
1621 mono_defaults.com_object_class = NULL;
1622 mono_defaults.com_interop_proxy_class = NULL;
1623 mono_defaults.iunknown_class = NULL;
1624 mono_defaults.idispatch_class = NULL;
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");
1632 mono_defaults.generic_ireadonlylist_class = mono_class_from_name (
1633 mono_defaults.corlib, "System.Collections.Generic", "IReadOnlyList`1");
1635 domain->friendly_name = g_path_get_basename (filename);
1637 _mono_debug_init_corlib (domain);
1645 * Creates the initial application domain and initializes the mono_defaults
1647 * This function is guaranteed to not run any IL code.
1648 * The runtime is initialized using the default runtime version.
1650 * Returns: the initial domain.
1653 mono_init (const char *domain_name)
1655 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1659 * mono_init_from_assembly:
1660 * @domain_name: name to give to the initial domain
1661 * @filename: filename to load on startup
1663 * Used by the runtime, users should use mono_jit_init instead.
1665 * Creates the initial application domain and initializes the mono_defaults
1667 * This function is guaranteed to not run any IL code.
1668 * The runtime is initialized using the runtime version required by the
1669 * provided executable. The version is determined by looking at the exe
1670 * configuration file and the version PE field)
1672 * Returns: the initial domain.
1675 mono_init_from_assembly (const char *domain_name, const char *filename)
1677 return mono_init_internal (domain_name, filename, NULL);
1681 * mono_init_version:
1683 * Used by the runtime, users should use mono_jit_init instead.
1685 * Creates the initial application domain and initializes the mono_defaults
1688 * This function is guaranteed to not run any IL code.
1689 * The runtime is initialized using the provided rutime version.
1691 * Returns: the initial domain.
1694 mono_init_version (const char *domain_name, const char *version)
1696 return mono_init_internal (domain_name, NULL, version);
1701 * mono_init_com_types:
1703 * Initializes all types needed for COM Interop in mono_defaults structure.
1706 mono_init_com_types (void)
1708 static gboolean initialized = FALSE;
1713 /* FIXME: do I need some threading protection here */
1715 g_assert (mono_defaults.corlib);
1717 mono_defaults.variant_class = mono_class_from_name (
1718 mono_defaults.corlib, "System", "Variant");
1719 g_assert (mono_defaults.variant_class != 0);
1721 mono_defaults.com_object_class = mono_class_from_name (
1722 mono_defaults.corlib, "System", "__ComObject");
1723 g_assert (mono_defaults.com_object_class != 0);
1725 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1726 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1727 g_assert (mono_defaults.com_interop_proxy_class != 0);
1729 mono_defaults.iunknown_class = mono_class_from_name (
1730 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1731 g_assert (mono_defaults.iunknown_class != 0);
1733 mono_defaults.idispatch_class = mono_class_from_name (
1734 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1735 g_assert (mono_defaults.idispatch_class != 0);
1739 #endif /*DISABLE_COM*/
1744 * Cleans up all metadata modules.
1749 mono_close_exe_image ();
1751 mono_defaults.corlib = NULL;
1753 mono_config_cleanup ();
1754 mono_loader_cleanup ();
1755 mono_classes_cleanup ();
1756 mono_assemblies_cleanup ();
1757 mono_images_cleanup ();
1758 mono_debug_cleanup ();
1759 mono_metadata_cleanup ();
1761 mono_native_tls_free (appdomain_thread_id);
1762 DeleteCriticalSection (&appdomains_mutex);
1770 mono_close_exe_image (void)
1773 mono_image_close (exe_image);
1777 * mono_get_root_domain:
1779 * The root AppDomain is the initial domain created by the runtime when it is
1780 * initialized. Programs execute on this AppDomain, but can create new ones
1781 * later. Currently there is no unmanaged API to create new AppDomains, this
1782 * must be done from managed code.
1784 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1787 mono_get_root_domain (void)
1789 return mono_root_domain;
1795 * Returns: the current domain, to obtain the root domain use
1796 * mono_get_root_domain().
1801 return GET_APPDOMAIN ();
1805 mono_domain_unset (void)
1807 SET_APPDOMAIN (NULL);
1811 mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception)
1813 MonoInternalThread *thread;
1815 if (mono_domain_get () == domain)
1818 SET_APPDOMAIN (domain);
1819 SET_APPCONTEXT (domain->default_context);
1821 if (migrate_exception) {
1822 thread = mono_thread_internal_current ();
1823 if (!thread->abort_exc)
1826 g_assert (thread->abort_exc->object.vtable->domain != domain);
1827 MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
1828 g_assert (thread->abort_exc->object.vtable->domain == domain);
1833 * mono_domain_set_internal:
1834 * @domain: the new domain
1836 * Sets the current domain to @domain.
1839 mono_domain_set_internal (MonoDomain *domain)
1841 mono_domain_set_internal_with_options (domain, TRUE);
1845 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1851 * Create a copy of the data to avoid calling the user callback
1852 * inside the lock because that could lead to deadlocks.
1853 * We can do this because this function is not perf. critical.
1855 mono_appdomains_lock ();
1856 size = appdomain_list_size;
1857 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1858 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1859 mono_appdomains_unlock ();
1861 for (i = 0; i < size; ++i) {
1863 func (copy [i], user_data);
1866 mono_gc_free_fixed (copy);
1870 * mono_domain_assembly_open:
1871 * @domain: the application domain
1872 * @name: file name of the assembly
1874 * fixme: maybe we should integrate this with mono_assembly_open ??
1877 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1879 MonoDomain *current;
1883 mono_domain_assemblies_lock (domain);
1884 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1886 if (strcmp (name, ass->aname.name) == 0) {
1887 mono_domain_assemblies_unlock (domain);
1891 mono_domain_assemblies_unlock (domain);
1893 if (domain != mono_domain_get ()) {
1894 current = mono_domain_get ();
1896 mono_domain_set (domain, FALSE);
1897 ass = mono_assembly_open (name, NULL);
1898 mono_domain_set (current, FALSE);
1900 ass = mono_assembly_open (name, NULL);
1907 unregister_vtable_reflection_type (MonoVTable *vtable)
1909 MonoObject *type = vtable->type;
1911 if (type->vtable->klass != mono_defaults.monotype_class)
1912 MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type);
1916 mono_domain_free (MonoDomain *domain, gboolean force)
1918 int code_size, code_alloc;
1920 if ((domain == mono_root_domain) && !force) {
1921 g_warning ("cant unload root domain");
1925 if (mono_dont_free_domains)
1928 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1930 mono_debug_domain_unload (domain);
1932 mono_appdomains_lock ();
1933 appdomains_list [domain->domain_id] = NULL;
1934 mono_appdomains_unlock ();
1936 /* must do this early as it accesses fields and types */
1937 if (domain->special_static_fields) {
1938 mono_alloc_special_static_data_free (domain->special_static_fields);
1939 g_hash_table_destroy (domain->special_static_fields);
1940 domain->special_static_fields = NULL;
1944 * We must destroy all these hash tables here because they
1945 * contain references to managed objects belonging to the
1946 * domain. Once we let the GC clear the domain there must be
1947 * no more such references, or we'll crash if a collection
1950 mono_g_hash_table_destroy (domain->ldstr_table);
1951 domain->ldstr_table = NULL;
1953 mono_g_hash_table_destroy (domain->env);
1956 if (domain->tlsrec_list) {
1957 mono_thread_destroy_domain_tls (domain);
1958 domain->tlsrec_list = NULL;
1961 mono_reflection_cleanup_domain (domain);
1963 if (domain->type_hash) {
1964 mono_g_hash_table_destroy (domain->type_hash);
1965 domain->type_hash = NULL;
1967 if (domain->type_init_exception_hash) {
1968 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1969 domain->type_init_exception_hash = NULL;
1972 if (domain->class_vtable_array) {
1974 for (i = 0; i < domain->class_vtable_array->len; ++i)
1975 unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i));
1978 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1979 MonoAssembly *ass = tmp->data;
1980 mono_assembly_release_gc_roots (ass);
1983 /* This needs to be done before closing assemblies */
1984 mono_gc_clear_domain (domain);
1986 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1987 MonoAssembly *ass = tmp->data;
1988 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);
1989 if (!mono_assembly_close_except_image_pools (ass))
1993 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1994 MonoAssembly *ass = tmp->data;
1996 mono_assembly_close_finish (ass);
1998 g_slist_free (domain->domain_assemblies);
1999 domain->domain_assemblies = NULL;
2002 * Send this after the assemblies have been unloaded and the domain is still in a
2005 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
2007 if (free_domain_hook)
2008 free_domain_hook (domain);
2010 /* FIXME: free delegate_hash_table when it's used */
2011 if (domain->search_path) {
2012 g_strfreev (domain->search_path);
2013 domain->search_path = NULL;
2015 domain->create_proxy_for_type_method = NULL;
2016 domain->private_invoke_method = NULL;
2017 domain->default_context = NULL;
2018 domain->out_of_memory_ex = NULL;
2019 domain->null_reference_ex = NULL;
2020 domain->stack_overflow_ex = NULL;
2021 domain->ephemeron_tombstone = NULL;
2022 domain->entry_assembly = NULL;
2024 g_free (domain->friendly_name);
2025 domain->friendly_name = NULL;
2026 g_ptr_array_free (domain->class_vtable_array, TRUE);
2027 domain->class_vtable_array = NULL;
2028 g_hash_table_destroy (domain->proxy_vtable_hash);
2029 domain->proxy_vtable_hash = NULL;
2030 if (domain->static_data_array) {
2031 mono_gc_free_fixed (domain->static_data_array);
2032 domain->static_data_array = NULL;
2034 mono_internal_hash_table_destroy (&domain->jit_code_hash);
2037 * There might still be jit info tables of this domain which
2038 * are not freed. Since the domain cannot be in use anymore,
2039 * this will free them.
2041 mono_thread_hazardous_try_free_all ();
2042 g_assert (domain->num_jit_info_tables == 1);
2043 jit_info_table_free (domain->jit_info_table);
2044 domain->jit_info_table = NULL;
2045 g_assert (!domain->jit_info_free_queue);
2047 /* collect statistics */
2048 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
2049 total_domain_code_alloc += code_alloc;
2050 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
2051 max_domain_code_size = MAX (max_domain_code_size, code_size);
2053 #ifdef DEBUG_DOMAIN_UNLOAD
2054 mono_mempool_invalidate (domain->mp);
2055 mono_code_manager_invalidate (domain->code_mp);
2057 #ifndef DISABLE_PERFCOUNTERS
2058 mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
2060 mono_mempool_destroy (domain->mp);
2062 mono_code_manager_destroy (domain->code_mp);
2063 domain->code_mp = NULL;
2066 g_hash_table_destroy (domain->finalizable_objects_hash);
2067 domain->finalizable_objects_hash = NULL;
2068 if (domain->method_rgctx_hash) {
2069 g_hash_table_destroy (domain->method_rgctx_hash);
2070 domain->method_rgctx_hash = NULL;
2072 if (domain->generic_virtual_cases) {
2073 g_hash_table_destroy (domain->generic_virtual_cases);
2074 domain->generic_virtual_cases = NULL;
2076 if (domain->generic_virtual_thunks) {
2077 g_hash_table_destroy (domain->generic_virtual_thunks);
2078 domain->generic_virtual_thunks = NULL;
2080 if (domain->ftnptrs_hash) {
2081 g_hash_table_destroy (domain->ftnptrs_hash);
2082 domain->ftnptrs_hash = NULL;
2085 DeleteCriticalSection (&domain->finalizable_objects_hash_lock);
2086 DeleteCriticalSection (&domain->assemblies_lock);
2087 DeleteCriticalSection (&domain->jit_code_hash_lock);
2088 DeleteCriticalSection (&domain->lock);
2089 domain->setup = NULL;
2091 mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
2093 /* FIXME: anything else required ? */
2095 mono_gc_free_fixed (domain);
2097 #ifndef DISABLE_PERFCOUNTERS
2098 mono_perfcounters->loader_appdomains--;
2101 if (domain == mono_root_domain)
2102 mono_root_domain = NULL;
2106 * mono_domain_get_id:
2109 * Returns: the a domain for a specific domain id.
2112 mono_domain_get_by_id (gint32 domainid)
2114 MonoDomain * domain;
2116 mono_appdomains_lock ();
2117 if (domainid < appdomain_list_size)
2118 domain = appdomains_list [domainid];
2121 mono_appdomains_unlock ();
2127 mono_domain_get_id (MonoDomain *domain)
2129 return domain->domain_id;
2133 * mono_domain_alloc:
2135 * LOCKING: Acquires the domain lock.
2138 mono_domain_alloc (MonoDomain *domain, guint size)
2142 mono_domain_lock (domain);
2143 #ifndef DISABLE_PERFCOUNTERS
2144 mono_perfcounters->loader_bytes += size;
2146 res = mono_mempool_alloc (domain->mp, size);
2147 mono_domain_unlock (domain);
2153 * mono_domain_alloc0:
2155 * LOCKING: Acquires the domain lock.
2158 mono_domain_alloc0 (MonoDomain *domain, guint size)
2162 mono_domain_lock (domain);
2163 #ifndef DISABLE_PERFCOUNTERS
2164 mono_perfcounters->loader_bytes += size;
2166 res = mono_mempool_alloc0 (domain->mp, size);
2167 mono_domain_unlock (domain);
2173 * mono_domain_code_reserve:
2175 * LOCKING: Acquires the domain lock.
2178 mono_domain_code_reserve (MonoDomain *domain, int size)
2182 mono_domain_lock (domain);
2183 res = mono_code_manager_reserve (domain->code_mp, size);
2184 mono_domain_unlock (domain);
2190 * mono_domain_code_reserve_align:
2192 * LOCKING: Acquires the domain lock.
2195 mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment)
2199 mono_domain_lock (domain);
2200 res = mono_code_manager_reserve_align (domain->code_mp, size, alignment);
2201 mono_domain_unlock (domain);
2207 * mono_domain_code_commit:
2209 * LOCKING: Acquires the domain lock.
2212 mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize)
2214 mono_domain_lock (domain);
2215 mono_code_manager_commit (domain->code_mp, data, size, newsize);
2216 mono_domain_unlock (domain);
2219 #if defined(__native_client_codegen__) && defined(__native_client__)
2221 * Given the temporary buffer (allocated by mono_domain_code_reserve) into which
2222 * we are generating code, return a pointer to the destination in the dynamic
2223 * code segment into which the code will be copied when mono_domain_code_commit
2225 * LOCKING: Acquires the domain lock.
2228 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2231 mono_domain_lock (domain);
2232 dest = nacl_code_manager_get_code_dest (domain->code_mp, data);
2233 mono_domain_unlock (domain);
2238 * Convenience function which calls mono_domain_code_commit to validate and copy
2239 * the code. The caller sets *buf_base and *buf_size to the start and size of
2240 * the buffer (allocated by mono_domain_code_reserve), and *code_end to the byte
2241 * after the last instruction byte. On return, *buf_base will point to the start
2242 * of the copied in the code segment, and *code_end will point after the end of
2246 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2248 guint8 *tmp = nacl_domain_get_code_dest (domain, *buf_base);
2249 mono_domain_code_commit (domain, *buf_base, buf_size, *code_end - *buf_base);
2250 *code_end = tmp + (*code_end - *buf_base);
2256 /* no-op versions of Native Client functions */
2259 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2265 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2272 * mono_domain_code_foreach:
2273 * Iterate over the code thunks of the code manager of @domain.
2275 * The @func callback MUST not take any locks. If it really needs to, it must respect
2276 * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety
2277 * LOCKING: Acquires the domain lock.
2281 mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data)
2283 mono_domain_lock (domain);
2284 mono_code_manager_foreach (domain->code_mp, func, user_data);
2285 mono_domain_unlock (domain);
2290 mono_context_set (MonoAppContext * new_context)
2292 SET_APPCONTEXT (new_context);
2296 mono_context_get (void)
2298 return GET_APPCONTEXT ();
2301 /* LOCKING: the caller holds the lock for this domain */
2303 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
2305 /* The first entry in the array is the index of the next free slot
2306 * and the total size of the array
2309 if (domain->static_data_array) {
2310 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
2311 next = GPOINTER_TO_INT (domain->static_data_array [0]);
2313 /* 'data' is allocated by alloc_fixed */
2314 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2));
2315 mono_gc_memmove (new_array, domain->static_data_array, sizeof (gpointer) * size);
2317 new_array [1] = GINT_TO_POINTER (size);
2318 mono_gc_free_fixed (domain->static_data_array);
2319 domain->static_data_array = new_array;
2323 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, MONO_GC_ROOT_DESCR_FOR_FIXED (size));
2325 new_array [0] = GINT_TO_POINTER (next);
2326 new_array [1] = GINT_TO_POINTER (size);
2327 domain->static_data_array = new_array;
2329 domain->static_data_array [next++] = data;
2330 domain->static_data_array [0] = GINT_TO_POINTER (next);
2334 mono_get_corlib (void)
2336 return mono_defaults.corlib;
2340 mono_get_object_class (void)
2342 return mono_defaults.object_class;
2346 mono_get_byte_class (void)
2348 return mono_defaults.byte_class;
2352 mono_get_void_class (void)
2354 return mono_defaults.void_class;
2358 mono_get_boolean_class (void)
2360 return mono_defaults.boolean_class;
2364 mono_get_sbyte_class (void)
2366 return mono_defaults.sbyte_class;
2370 mono_get_int16_class (void)
2372 return mono_defaults.int16_class;
2376 mono_get_uint16_class (void)
2378 return mono_defaults.uint16_class;
2382 mono_get_int32_class (void)
2384 return mono_defaults.int32_class;
2388 mono_get_uint32_class (void)
2390 return mono_defaults.uint32_class;
2394 mono_get_intptr_class (void)
2396 return mono_defaults.int_class;
2400 mono_get_uintptr_class (void)
2402 return mono_defaults.uint_class;
2406 mono_get_int64_class (void)
2408 return mono_defaults.int64_class;
2412 mono_get_uint64_class (void)
2414 return mono_defaults.uint64_class;
2418 mono_get_single_class (void)
2420 return mono_defaults.single_class;
2424 mono_get_double_class (void)
2426 return mono_defaults.double_class;
2430 mono_get_char_class (void)
2432 return mono_defaults.char_class;
2436 mono_get_string_class (void)
2438 return mono_defaults.string_class;
2442 mono_get_enum_class (void)
2444 return mono_defaults.enum_class;
2448 mono_get_array_class (void)
2450 return mono_defaults.array_class;
2454 mono_get_thread_class (void)
2456 return mono_defaults.thread_class;
2460 mono_get_exception_class (void)
2462 return mono_defaults.exception_class;
2466 static char* get_attribute_value (const gchar **attribute_names,
2467 const gchar **attribute_values,
2468 const char *att_name)
2471 for (n=0; attribute_names[n] != NULL; n++) {
2472 if (strcmp (attribute_names[n], att_name) == 0)
2473 return g_strdup (attribute_values[n]);
2478 static void start_element (GMarkupParseContext *context,
2479 const gchar *element_name,
2480 const gchar **attribute_names,
2481 const gchar **attribute_values,
2485 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2487 if (strcmp (element_name, "configuration") == 0) {
2488 app_config->configuration_count++;
2491 if (strcmp (element_name, "startup") == 0) {
2492 app_config->startup_count++;
2496 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2499 if (strcmp (element_name, "requiredRuntime") == 0) {
2500 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2501 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2502 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2503 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2507 static void end_element (GMarkupParseContext *context,
2508 const gchar *element_name,
2512 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2514 if (strcmp (element_name, "configuration") == 0) {
2515 app_config->configuration_count--;
2516 } else if (strcmp (element_name, "startup") == 0) {
2517 app_config->startup_count--;
2521 static const GMarkupParser
2530 static AppConfigInfo *
2531 app_config_parse (const char *exe_filename)
2533 AppConfigInfo *app_config;
2534 GMarkupParseContext *context;
2537 const char *bundled_config;
2538 char *config_filename;
2540 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2542 if (bundled_config) {
2543 text = g_strdup (bundled_config);
2544 len = strlen (text);
2546 config_filename = g_strconcat (exe_filename, ".config", NULL);
2548 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2549 g_free (config_filename);
2552 g_free (config_filename);
2555 app_config = g_new0 (AppConfigInfo, 1);
2557 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2558 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2559 g_markup_parse_context_end_parse (context, NULL);
2561 g_markup_parse_context_free (context);
2567 app_config_free (AppConfigInfo* app_config)
2570 GSList *list = app_config->supported_runtimes;
2571 while (list != NULL) {
2572 rt = (char*)list->data;
2574 list = g_slist_next (list);
2576 g_slist_free (app_config->supported_runtimes);
2577 g_free (app_config->required_runtime);
2578 g_free (app_config);
2582 static const MonoRuntimeInfo*
2583 get_runtime_by_version (const char *version)
2586 int max = G_N_ELEMENTS (supported_runtimes);
2592 for (n=0; n<max; n++) {
2593 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2594 return &supported_runtimes[n];
2597 vlen = strlen (version);
2598 if (vlen >= 4 && version [1] - '0' >= 4) {
2599 for (n=0; n<max; n++) {
2600 if (strncmp (version, supported_runtimes[n].runtime_version, 4) == 0)
2601 return &supported_runtimes[n];
2609 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2611 AppConfigInfo* app_config;
2613 const MonoRuntimeInfo* runtime = NULL;
2614 MonoImage *image = NULL;
2616 app_config = app_config_parse (exe_file);
2618 if (app_config != NULL) {
2619 /* Check supportedRuntime elements, if none is supported, fail.
2620 * If there are no such elements, look for a requiredRuntime element.
2622 if (app_config->supported_runtimes != NULL) {
2624 GSList *list = app_config->supported_runtimes;
2625 while (list != NULL) {
2626 version = (char*) list->data;
2627 runtime = get_runtime_by_version (version);
2628 if (runtime != NULL)
2629 runtimes [n++] = runtime;
2630 list = g_slist_next (list);
2632 runtimes [n] = NULL;
2633 app_config_free (app_config);
2637 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2638 if (app_config->required_runtime != NULL) {
2639 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2640 runtimes [1] = NULL;
2641 app_config_free (app_config);
2644 app_config_free (app_config);
2647 /* Look for a runtime with the exact version */
2648 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2651 image = mono_image_open (exe_file, NULL);
2653 if (image == NULL) {
2654 /* The image is wrong or the file was not found. In this case return
2655 * a default runtime and leave to the initialization method the work of
2656 * reporting the error.
2658 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2659 runtimes [1] = NULL;
2665 runtimes [0] = get_runtime_by_version (image->version);
2666 runtimes [1] = NULL;
2671 * mono_get_runtime_info:
2673 * Returns: the version of the current runtime instance.
2675 const MonoRuntimeInfo*
2676 mono_get_runtime_info (void)
2678 return current_runtime;
2682 mono_debugger_check_runtime_version (const char *filename)
2684 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2685 const MonoRuntimeInfo *rinfo;
2688 get_runtimes_from_exe (filename, &image, runtimes);
2689 rinfo = runtimes [0];
2692 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2694 if (rinfo != current_runtime)
2695 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2696 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2697 filename, rinfo->runtime_version);
2703 * mono_framework_version:
2705 * Return the major version of the framework curently executing.
2708 mono_framework_version (void)
2710 return current_runtime->framework_version [0] - '0';