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)
17 #include <mono/metadata/gc-internal.h>
19 #include <mono/utils/mono-compiler.h>
20 #include <mono/utils/mono-logger.h>
21 #include <mono/utils/mono-membar.h>
22 #include <mono/utils/mono-counters.h>
23 #include <mono/metadata/object.h>
24 #include <mono/metadata/object-internals.h>
25 #include <mono/metadata/domain-internals.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/assembly.h>
28 #include <mono/metadata/exception.h>
29 #include <mono/metadata/metadata-internals.h>
30 #include <mono/metadata/gc-internal.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-debug-debugger.h>
33 #include <mono/metadata/mono-config.h>
34 #include <mono/metadata/threads-types.h>
35 #include <metadata/threads.h>
36 #include <metadata/profiler-private.h>
37 #include <mono/metadata/coree.h>
39 /* #define DEBUG_DOMAIN_UNLOAD */
41 /* we need to use both the Tls* functions and __thread because
42 * some archs may generate faster jit code with one meachanism
43 * or the other (we used to do it because tls slots were GC-tracked,
44 * but we can't depend on this).
46 static guint32 appdomain_thread_id = -1;
49 * Avoid calling TlsSetValue () if possible, since in the io-layer, it acquires
50 * a global lock (!) so it is a contention point.
52 #if (defined(__i386__) || defined(__x86_64__)) && !defined(PLATFORM_WIN32)
53 #define NO_TLS_SET_VALUE
58 static __thread MonoDomain * tls_appdomain MONO_TLS_FAST;
60 #define GET_APPDOMAIN() tls_appdomain
62 #ifdef NO_TLS_SET_VALUE
63 #define SET_APPDOMAIN(x) do { \
67 #define SET_APPDOMAIN(x) do { \
69 TlsSetValue (appdomain_thread_id, x); \
73 #else /* !HAVE_KW_THREAD */
75 #define GET_APPDOMAIN() ((MonoDomain *)TlsGetValue (appdomain_thread_id))
76 #define SET_APPDOMAIN(x) TlsSetValue (appdomain_thread_id, x);
80 #define GET_APPCONTEXT() (mono_thread_current ()->current_appcontext)
81 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_current (), current_appcontext, (x))
83 static guint16 appdomain_list_size = 0;
84 static guint16 appdomain_next = 0;
85 static MonoDomain **appdomains_list = NULL;
86 static MonoImage *exe_image;
88 gboolean mono_dont_free_domains;
90 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
91 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
92 static CRITICAL_SECTION appdomains_mutex;
94 static MonoDomain *mono_root_domain = NULL;
97 static int max_domain_code_size = 0;
98 static int max_domain_code_alloc = 0;
99 static int total_domain_code_alloc = 0;
101 /* AppConfigInfo: Information about runtime versions supported by an
105 GSList *supported_runtimes;
106 char *required_runtime;
107 int configuration_count;
112 * AotModuleInfo: Contains information about AOT modules.
119 static const MonoRuntimeInfo *current_runtime = NULL;
121 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
124 * Contains information about AOT loaded code.
126 static MonoAotModuleInfoTable *aot_modules = NULL;
128 /* This is the list of runtime versions supported by this JIT.
130 static const MonoRuntimeInfo supported_runtimes[] = {
131 {"v1.0.3705", "1.0", { {1,0,5000,0}, {7,0,5000,0} } },
132 {"v1.1.4322", "1.0", { {1,0,5000,0}, {7,0,5000,0} } },
133 {"v2.0.50215","2.0", { {2,0,0,0}, {8,0,0,0} } },
134 {"v2.0.50727","2.0", { {2,0,0,0}, {8,0,0,0} } },
135 {"moonlight", "2.1", { {2,0,5,0}, {9,0,0,0} } },
139 /* The stable runtime version */
140 #define DEFAULT_RUNTIME_VERSION "v1.1.4322"
142 /* Callbacks installed by the JIT */
143 static MonoCreateDomainFunc create_domain_hook;
144 static MonoFreeDomainFunc free_domain_hook;
146 /* This is intentionally not in the header file, so people don't misuse it. */
147 extern void _mono_debug_init_corlib (MonoDomain *domain);
150 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
152 static const MonoRuntimeInfo*
153 get_runtime_by_version (const char *version);
156 mono_jit_info_find_aot_module (guint8* addr);
159 mono_domain_get_tls_key (void)
161 #ifdef NO_TLS_SET_VALUE
162 g_assert_not_reached ();
165 return appdomain_thread_id;
170 mono_domain_get_tls_offset (void)
173 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
174 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
179 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
180 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
181 #define JIT_INFO_TABLE_FILLED_NUM_ELEMENTS (MONO_JIT_INFO_TABLE_CHUNK_SIZE * JIT_INFO_TABLE_FILL_RATIO_NOM / JIT_INFO_TABLE_FILL_RATIO_DENOM)
183 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
184 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
186 #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
187 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
189 #define JIT_INFO_TABLE_HAZARD_INDEX 0
190 #define JIT_INFO_HAZARD_INDEX 1
193 jit_info_table_num_elements (MonoJitInfoTable *table)
196 int num_elements = 0;
198 for (i = 0; i < table->num_chunks; ++i) {
199 MonoJitInfoTableChunk *chunk = table->chunks [i];
200 int chunk_num_elements = chunk->num_elements;
203 for (j = 0; j < chunk_num_elements; ++j) {
204 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
212 static MonoJitInfoTableChunk*
213 jit_info_table_new_chunk (void)
215 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
221 static MonoJitInfoTable *
222 jit_info_table_new (MonoDomain *domain)
224 MonoJitInfoTable *table = g_malloc0 (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*));
226 table->domain = domain;
227 table->num_chunks = 1;
228 table->chunks [0] = jit_info_table_new_chunk ();
234 jit_info_table_free (MonoJitInfoTable *table)
237 int num_chunks = table->num_chunks;
238 MonoDomain *domain = table->domain;
240 mono_domain_lock (domain);
242 table->domain->num_jit_info_tables--;
243 if (table->domain->num_jit_info_tables <= 1) {
246 for (list = table->domain->jit_info_free_queue; list; list = list->next)
249 g_slist_free (table->domain->jit_info_free_queue);
250 table->domain->jit_info_free_queue = NULL;
253 /* At this point we assume that there are no other threads
254 still accessing the table, so we don't have to worry about
255 hazardous pointers. */
257 for (i = 0; i < num_chunks; ++i) {
258 MonoJitInfoTableChunk *chunk = table->chunks [i];
262 if (--chunk->refcount > 0)
265 num_elements = chunk->num_elements;
266 for (j = 0; j < num_elements; ++j) {
267 MonoJitInfo *ji = chunk->data [j];
269 if (IS_JIT_INFO_TOMBSTONE (ji))
276 mono_domain_unlock (domain);
281 /* Can be called with hp==NULL, in which case it acts as an ordinary
282 pointer fetch. It's used that way indirectly from
283 mono_jit_info_table_add(), which doesn't have to care about hazards
284 because it holds the respective domain lock. */
286 get_hazardous_pointer (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index)
291 /* Get the pointer */
293 /* If we don't have hazard pointers just return the
297 /* Make it hazardous */
298 mono_hazard_pointer_set (hp, hazard_index, p);
299 /* Check that it's still the same. If not, try
302 mono_hazard_pointer_clear (hp, hazard_index);
311 /* The jit_info_table is sorted in ascending order by the end
312 * addresses of the compiled methods. The reason why we have to do
313 * this is that once we introduce tombstones, it becomes possible for
314 * code ranges to overlap, and if we sort by code start and insert at
315 * the back of the table, we cannot guarantee that we won't overlook
318 * There are actually two possible ways to do the sorting and
319 * inserting which work with our lock-free mechanism:
321 * 1. Sort by start address and insert at the front. When looking for
322 * an entry, find the last one with a start address lower than the one
323 * you're looking for, then work your way to the front of the table.
325 * 2. Sort by end address and insert at the back. When looking for an
326 * entry, find the first one with an end address higher than the one
327 * you're looking for, then work your way to the end of the table.
329 * We chose the latter out of convenience.
332 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
334 int left = 0, right = table->num_chunks;
336 g_assert (left < right);
339 int pos = (left + right) / 2;
340 MonoJitInfoTableChunk *chunk = table->chunks [pos];
342 if (addr < chunk->last_code_end)
346 } while (left < right);
347 g_assert (left == right);
349 if (left >= table->num_chunks)
350 return table->num_chunks - 1;
355 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
357 int left = 0, right = chunk->num_elements;
359 while (left < right) {
360 int pos = (left + right) / 2;
361 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
362 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
369 g_assert (left == right);
375 mono_jit_info_table_find (MonoDomain *domain, char *addr)
377 MonoJitInfoTable *table;
380 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
382 ++mono_stats.jit_info_table_lookup_count;
384 /* First we have to get the domain's jit_info_table. This is
385 complicated by the fact that a writer might substitute a
386 new table and free the old one. What the writer guarantees
387 us is that it looks at the hazard pointers after it has
388 changed the jit_info_table pointer. So, if we guard the
389 table by a hazard pointer and make sure that the pointer is
390 still there after we've made it hazardous, we don't have to
391 worry about the writer freeing the table. */
392 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
394 chunk_pos = jit_info_table_index (table, (gint8*)addr);
395 g_assert (chunk_pos < table->num_chunks);
397 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
399 /* We now have a position that's very close to that of the
400 first element whose end address is higher than the one
401 we're looking for. If we don't have the exact position,
402 then we have a position below that one, so we'll just
403 search upward until we find our element. */
405 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
407 while (pos < chunk->num_elements) {
408 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
412 if (IS_JIT_INFO_TOMBSTONE (ji)) {
413 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
416 if ((gint8*)addr >= (gint8*)ji->code_start
417 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
418 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
419 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
423 /* If we find a non-tombstone element which is already
424 beyond what we're looking for, we have to end the
426 if ((gint8*)addr < (gint8*)ji->code_start)
432 } while (chunk_pos < table->num_chunks);
435 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
436 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
438 /* maybe it is shared code, so we also search in the root domain */
440 if (domain != mono_root_domain)
441 ji = mono_jit_info_table_find (mono_root_domain, addr);
444 /* Maybe its an AOT module */
445 MonoImage *image = mono_jit_info_find_aot_module ((guint8*)addr);
447 ji = jit_info_find_in_aot_func (domain, image, addr);
453 static G_GNUC_UNUSED void
454 jit_info_table_check (MonoJitInfoTable *table)
458 for (i = 0; i < table->num_chunks; ++i) {
459 MonoJitInfoTableChunk *chunk = table->chunks [i];
462 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
463 if (chunk->refcount > 10)
464 printf("warning: chunk refcount is %d\n", chunk->refcount);
465 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
467 for (j = 0; j < chunk->num_elements; ++j) {
468 MonoJitInfo *this = chunk->data [j];
471 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
473 if (j < chunk->num_elements - 1)
474 next = chunk->data [j + 1];
475 else if (i < table->num_chunks - 1) {
478 for (k = i + 1; k < table->num_chunks; ++k)
479 if (table->chunks [k]->num_elements > 0)
482 if (k >= table->num_chunks)
485 g_assert (table->chunks [k]->num_elements > 0);
486 next = table->chunks [k]->data [0];
490 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
495 static MonoJitInfoTable*
496 jit_info_table_realloc (MonoJitInfoTable *old)
499 int num_elements = jit_info_table_num_elements (old);
502 int new_chunk, new_element;
503 MonoJitInfoTable *new;
505 /* number of needed places for elements needed */
506 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
507 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
509 new = g_malloc (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*) * num_chunks);
510 new->domain = old->domain;
511 new->num_chunks = num_chunks;
513 for (i = 0; i < num_chunks; ++i)
514 new->chunks [i] = jit_info_table_new_chunk ();
518 for (i = 0; i < old->num_chunks; ++i) {
519 MonoJitInfoTableChunk *chunk = old->chunks [i];
520 int chunk_num_elements = chunk->num_elements;
523 for (j = 0; j < chunk_num_elements; ++j) {
524 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
525 g_assert (new_chunk < num_chunks);
526 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
527 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
528 new->chunks [new_chunk]->num_elements = new_element;
536 if (new_chunk < num_chunks) {
537 g_assert (new_chunk == num_chunks - 1);
538 new->chunks [new_chunk]->num_elements = new_element;
539 g_assert (new->chunks [new_chunk]->num_elements > 0);
542 for (i = 0; i < num_chunks; ++i) {
543 MonoJitInfoTableChunk *chunk = new->chunks [i];
544 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
546 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
553 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
555 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
556 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
558 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
560 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
561 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
563 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
564 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
566 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
567 + new1->data [new1->num_elements - 1]->code_size;
568 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
569 + new2->data [new2->num_elements - 1]->code_size;
575 static MonoJitInfoTable*
576 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
578 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
579 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
582 new_table->domain = table->domain;
583 new_table->num_chunks = table->num_chunks + 1;
586 for (i = 0; i < table->num_chunks; ++i) {
587 if (table->chunks [i] == chunk) {
588 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
591 new_table->chunks [j] = table->chunks [i];
592 ++new_table->chunks [j]->refcount;
597 g_assert (j == new_table->num_chunks);
602 static MonoJitInfoTableChunk*
603 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
605 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
609 for (i = 0; i < old->num_elements; ++i) {
610 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
611 new->data [j++] = old->data [i];
614 new->num_elements = j;
615 if (new->num_elements > 0)
616 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
618 new->last_code_end = old->last_code_end;
623 static MonoJitInfoTable*
624 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
626 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
627 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
630 new_table->domain = table->domain;
631 new_table->num_chunks = table->num_chunks;
634 for (i = 0; i < table->num_chunks; ++i) {
635 if (table->chunks [i] == chunk)
636 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
638 new_table->chunks [j] = table->chunks [i];
639 ++new_table->chunks [j]->refcount;
644 g_assert (j == new_table->num_chunks);
649 /* As we add an element to the table the case can arise that the chunk
650 * to which we need to add is already full. In that case we have to
651 * allocate a new table and do something about that chunk. We have
652 * several strategies:
654 * If the number of elements in the table is below the low watermark
655 * or above the high watermark, we reallocate the whole table.
656 * Otherwise we only concern ourselves with the overflowing chunk:
658 * If there are no tombstones in the chunk then we split the chunk in
659 * two, each half full.
661 * If the chunk does contain tombstones, we just make a new copy of
662 * the chunk without the tombstones, which will have room for at least
663 * the one element we have to add.
665 static MonoJitInfoTable*
666 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
668 int num_elements = jit_info_table_num_elements (table);
671 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
672 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
673 //printf ("reallocing table\n");
674 return jit_info_table_realloc (table);
677 /* count the number of non-tombstone elements in the chunk */
679 for (i = 0; i < chunk->num_elements; ++i) {
680 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
684 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
685 //printf ("splitting chunk\n");
686 return jit_info_table_copy_and_split_chunk (table, chunk);
689 //printf ("purifying chunk\n");
690 return jit_info_table_copy_and_purify_chunk (table, chunk);
693 /* We add elements to the table by first making space for them by
694 * shifting the elements at the back to the right, one at a time.
695 * This results in duplicate entries during the process, but during
696 * all the time the table is in a sorted state. Also, when an element
697 * is replaced by another one, the element that replaces it has an end
698 * address that is equal to or lower than that of the replaced
699 * element. That property is necessary to guarantee that when
700 * searching for an element we end up at a position not higher than
701 * the one we're looking for (i.e. we either find the element directly
702 * or we end up to the left of it).
705 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
707 MonoJitInfoTable *table;
709 MonoJitInfoTableChunk *chunk;
713 g_assert (ji->method != NULL);
715 mono_domain_lock (domain);
717 ++mono_stats.jit_info_table_insert_count;
719 table = domain->jit_info_table;
722 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
723 g_assert (chunk_pos < table->num_chunks);
724 chunk = table->chunks [chunk_pos];
726 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
727 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
729 /* Debugging code, should be removed. */
730 //jit_info_table_check (new_table);
732 domain->jit_info_table = new_table;
733 mono_memory_barrier ();
734 domain->num_jit_info_tables++;
735 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free);
741 /* Debugging code, should be removed. */
742 //jit_info_table_check (table);
744 num_elements = chunk->num_elements;
746 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
748 /* First we need to size up the chunk by one, by copying the
749 last item, or inserting the first one, if the table is
751 if (num_elements > 0)
752 chunk->data [num_elements] = chunk->data [num_elements - 1];
754 chunk->data [0] = ji;
755 mono_memory_write_barrier ();
756 chunk->num_elements = ++num_elements;
758 /* Shift the elements up one by one. */
759 for (i = num_elements - 2; i >= pos; --i) {
760 mono_memory_write_barrier ();
761 chunk->data [i + 1] = chunk->data [i];
764 /* Now we have room and can insert the new item. */
765 mono_memory_write_barrier ();
766 chunk->data [pos] = ji;
768 /* Set the high code end address chunk entry. */
769 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
770 + chunk->data [chunk->num_elements - 1]->code_size;
772 /* Debugging code, should be removed. */
773 //jit_info_table_check (table);
775 mono_domain_unlock (domain);
779 mono_jit_info_make_tombstone (MonoJitInfo *ji)
781 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
783 tombstone->code_start = ji->code_start;
784 tombstone->code_size = ji->code_size;
785 tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
791 * LOCKING: domain lock
794 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
796 if (domain->num_jit_info_tables <= 1) {
797 /* Can it actually happen that we only have one table
798 but ji is still hazardous? */
799 mono_thread_hazardous_free_or_queue (ji, g_free);
801 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
806 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
808 MonoJitInfoTable *table;
809 MonoJitInfoTableChunk *chunk;
810 gpointer start = ji->code_start;
813 mono_domain_lock (domain);
814 table = domain->jit_info_table;
816 ++mono_stats.jit_info_table_remove_count;
818 chunk_pos = jit_info_table_index (table, start);
819 g_assert (chunk_pos < table->num_chunks);
821 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
824 chunk = table->chunks [chunk_pos];
826 while (pos < chunk->num_elements) {
827 if (chunk->data [pos] == ji)
830 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
831 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
832 <= (guint8*)ji->code_start + ji->code_size);
839 } while (chunk_pos < table->num_chunks);
842 g_assert (chunk->data [pos] == ji);
844 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
846 /* Debugging code, should be removed. */
847 //jit_info_table_check (table);
849 mono_jit_info_free_or_queue (domain, ji);
851 mono_domain_unlock (domain);
854 static MonoAotModuleInfoTable*
855 mono_aot_module_info_table_new (void)
857 return g_array_new (FALSE, FALSE, sizeof (gpointer));
861 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
863 int left = 0, right = table->len;
865 while (left < right) {
866 int pos = (left + right) / 2;
867 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
868 char *start = ainfo->start;
869 char *end = ainfo->end;
873 else if (addr >= end)
883 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
885 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
888 ainfo->image = image;
889 ainfo->start = start;
892 mono_appdomains_lock ();
895 aot_modules = mono_aot_module_info_table_new ();
897 pos = aot_info_table_index (aot_modules, start);
899 g_array_insert_val (aot_modules, pos, ainfo);
901 mono_appdomains_unlock ();
905 mono_jit_info_find_aot_module (guint8* addr)
907 guint left = 0, right;
912 mono_appdomains_lock ();
914 right = aot_modules->len;
915 while (left < right) {
916 guint pos = (left + right) / 2;
917 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
919 if (addr < (guint8*)ai->start)
921 else if (addr >= (guint8*)ai->end)
924 mono_appdomains_unlock ();
929 mono_appdomains_unlock ();
935 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
937 jit_info_find_in_aot_func = func;
941 mono_jit_info_get_code_start (MonoJitInfo* ji)
943 return ji->code_start;
947 mono_jit_info_get_code_size (MonoJitInfo* ji)
949 return ji->code_size;
953 mono_jit_info_get_method (MonoJitInfo* ji)
959 jit_info_key_extract (gpointer value)
961 MonoJitInfo *info = (MonoJitInfo*)value;
967 jit_info_next_value (gpointer value)
969 MonoJitInfo *info = (MonoJitInfo*)value;
971 return (gpointer*)&info->next_jit_code_hash;
975 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
977 mono_internal_hash_table_init (jit_code_hash,
978 mono_aligned_addr_hash,
979 jit_info_key_extract,
980 jit_info_next_value);
984 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
986 if (ji->has_generic_jit_info)
987 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
993 * mono_jit_info_get_generic_sharing_context:
996 * Returns the jit info's generic sharing context, or NULL if it
999 MonoGenericSharingContext*
1000 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
1002 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
1005 return gi->generic_sharing_context;
1011 * mono_jit_info_set_generic_sharing_context:
1013 * @gsctx: a generic sharing context
1015 * Sets the jit info's generic sharing context. The jit info must
1016 * have memory allocated for the context.
1019 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
1021 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
1025 gi->generic_sharing_context = gsctx;
1029 mono_install_create_domain_hook (MonoCreateDomainFunc func)
1031 create_domain_hook = func;
1035 mono_install_free_domain_hook (MonoFreeDomainFunc func)
1037 free_domain_hook = func;
1041 * mono_string_equal:
1042 * @s1: First string to compare
1043 * @s2: Second string to compare
1045 * Returns FALSE if the strings differ.
1048 mono_string_equal (MonoString *s1, MonoString *s2)
1050 int l1 = mono_string_length (s1);
1051 int l2 = mono_string_length (s2);
1058 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
1063 * @s: the string to hash
1065 * Returns the hash for the string.
1068 mono_string_hash (MonoString *s)
1070 const guint16 *p = mono_string_chars (s);
1071 int i, len = mono_string_length (s);
1074 for (i = 0; i < len; i++) {
1075 h = (h << 5) - h + *p;
1083 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1085 int len = GPOINTER_TO_INT (s1 [0]);
1086 if (len != GPOINTER_TO_INT (s2 [0]))
1089 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1093 mono_ptrarray_hash (gpointer *s)
1096 int len = GPOINTER_TO_INT (s [0]);
1099 for (i = 1; i < len; i++)
1100 hash += GPOINTER_TO_UINT (s [i]);
1106 * Allocate an id for domain and set domain->domain_id.
1107 * LOCKING: must be called while holding appdomains_mutex.
1108 * We try to assign low numbers to the domain, so it can be used
1109 * as an index in data tables to lookup domain-specific info
1110 * with minimal memory overhead. We also try not to reuse the
1111 * same id too quickly (to help debugging).
1114 domain_id_alloc (MonoDomain *domain)
1117 if (!appdomains_list) {
1118 appdomain_list_size = 2;
1119 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1121 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1122 if (!appdomains_list [i]) {
1128 for (i = 0; i < appdomain_next; ++i) {
1129 if (!appdomains_list [i]) {
1136 MonoDomain **new_list;
1137 int new_size = appdomain_list_size * 2;
1138 if (new_size >= (1 << 16))
1139 g_assert_not_reached ();
1140 id = appdomain_list_size;
1141 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1142 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1143 mono_gc_free_fixed (appdomains_list);
1144 appdomains_list = new_list;
1145 appdomain_list_size = new_size;
1147 domain->domain_id = id;
1148 appdomains_list [id] = domain;
1150 if (appdomain_next > appdomain_list_size)
1155 static guint32 domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1156 static gpointer domain_gc_desc = NULL;
1157 static guint32 domain_shadow_serial = 0L;
1160 mono_domain_create (void)
1163 guint32 shadow_serial;
1165 mono_appdomains_lock ();
1166 shadow_serial = domain_shadow_serial++;
1168 if (!domain_gc_desc) {
1169 unsigned int i, bit = 0;
1170 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1171 bit = i / sizeof (gpointer);
1172 domain_gc_bitmap [bit / 32] |= 1 << (bit % 32);
1174 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1176 mono_appdomains_unlock ();
1178 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1179 domain->shadow_serial = shadow_serial;
1180 domain->domain = NULL;
1181 domain->setup = NULL;
1182 domain->friendly_name = NULL;
1183 domain->search_path = NULL;
1185 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);
1187 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1189 domain->mp = mono_mempool_new ();
1190 domain->code_mp = mono_code_manager_new ();
1191 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1192 domain->domain_assemblies = NULL;
1193 domain->class_vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1194 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1195 domain->static_data_array = NULL;
1196 mono_jit_code_hash_init (&domain->jit_code_hash);
1197 domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1198 domain->num_jit_info_tables = 1;
1199 domain->jit_info_table = jit_info_table_new (domain);
1200 domain->jit_info_free_queue = NULL;
1201 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1202 domain->track_resurrection_handles_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1204 InitializeCriticalSection (&domain->lock);
1205 InitializeCriticalSection (&domain->assemblies_lock);
1206 InitializeCriticalSection (&domain->jit_code_hash_lock);
1207 InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
1209 domain->method_rgctx_hash = NULL;
1211 mono_appdomains_lock ();
1212 domain_id_alloc (domain);
1213 mono_appdomains_unlock ();
1215 mono_perfcounters->loader_appdomains++;
1216 mono_perfcounters->loader_total_appdomains++;
1218 mono_debug_domain_create (domain);
1220 if (create_domain_hook)
1221 create_domain_hook (domain);
1223 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1229 * mono_init_internal:
1231 * Creates the initial application domain and initializes the mono_defaults
1233 * This function is guaranteed to not run any IL code.
1234 * If exe_filename is not NULL, the method will determine the required runtime
1235 * from the exe configuration file or the version PE field.
1236 * If runtime_version is not NULL, that runtime version will be used.
1237 * Either exe_filename or runtime_version must be provided.
1239 * Returns: the initial domain.
1242 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1244 static MonoDomain *domain = NULL;
1245 MonoAssembly *ass = NULL;
1246 MonoImageOpenStatus status = MONO_IMAGE_OK;
1247 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1251 g_assert_not_reached ();
1253 #ifdef PLATFORM_WIN32
1254 /* Avoid system error message boxes. */
1255 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1257 mono_load_coree (exe_filename);
1260 mono_perfcounters_init ();
1262 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1263 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1264 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1266 mono_gc_base_init ();
1268 appdomain_thread_id = TlsAlloc ();
1270 InitializeCriticalSection (&appdomains_mutex);
1272 mono_metadata_init ();
1273 mono_images_init ();
1274 mono_assemblies_init ();
1275 mono_classes_init ();
1276 mono_loader_init ();
1277 mono_reflection_init ();
1279 /* FIXME: When should we release this memory? */
1280 MONO_GC_REGISTER_ROOT (appdomains_list);
1282 domain = mono_domain_create ();
1283 mono_root_domain = domain;
1285 SET_APPDOMAIN (domain);
1287 /* Get a list of runtimes supported by the exe */
1288 if (exe_filename != NULL) {
1290 * This function will load the exe file as a MonoImage. We need to close it, but
1291 * that would mean it would be reloaded later. So instead, we save it to
1292 * exe_image, and close it during shutdown.
1294 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1295 #ifdef PLATFORM_WIN32
1297 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1299 exe_image = mono_image_open (exe_filename, NULL);
1301 mono_fixup_exe_image (exe_image);
1303 } else if (runtime_version != NULL) {
1304 runtimes [0] = get_runtime_by_version (runtime_version);
1305 runtimes [1] = NULL;
1308 if (runtimes [0] == NULL) {
1309 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1310 runtimes [0] = default_runtime;
1311 runtimes [1] = NULL;
1312 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1313 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1316 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1317 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1318 current_runtime = runtimes [n];
1319 ass = mono_assembly_load_corlib (current_runtime, &status);
1320 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1325 /* Now that we have a runtime, set the policy for unhandled exceptions */
1326 if (mono_framework_version () < 2) {
1327 mono_runtime_unhandled_exception_policy_set (MONO_UNHANDLED_POLICY_LEGACY);
1330 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1332 case MONO_IMAGE_ERROR_ERRNO: {
1333 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1334 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1335 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1336 g_free (corlib_file);
1339 case MONO_IMAGE_IMAGE_INVALID:
1340 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1341 mono_assembly_getrootdir ());
1343 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1344 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1345 mono_assembly_getrootdir ());
1348 /* to suppress compiler warning */
1354 mono_defaults.corlib = mono_assembly_get_image (ass);
1356 mono_defaults.object_class = mono_class_from_name (
1357 mono_defaults.corlib, "System", "Object");
1358 g_assert (mono_defaults.object_class != 0);
1360 mono_defaults.void_class = mono_class_from_name (
1361 mono_defaults.corlib, "System", "Void");
1362 g_assert (mono_defaults.void_class != 0);
1364 mono_defaults.boolean_class = mono_class_from_name (
1365 mono_defaults.corlib, "System", "Boolean");
1366 g_assert (mono_defaults.boolean_class != 0);
1368 mono_defaults.byte_class = mono_class_from_name (
1369 mono_defaults.corlib, "System", "Byte");
1370 g_assert (mono_defaults.byte_class != 0);
1372 mono_defaults.sbyte_class = mono_class_from_name (
1373 mono_defaults.corlib, "System", "SByte");
1374 g_assert (mono_defaults.sbyte_class != 0);
1376 mono_defaults.int16_class = mono_class_from_name (
1377 mono_defaults.corlib, "System", "Int16");
1378 g_assert (mono_defaults.int16_class != 0);
1380 mono_defaults.uint16_class = mono_class_from_name (
1381 mono_defaults.corlib, "System", "UInt16");
1382 g_assert (mono_defaults.uint16_class != 0);
1384 mono_defaults.int32_class = mono_class_from_name (
1385 mono_defaults.corlib, "System", "Int32");
1386 g_assert (mono_defaults.int32_class != 0);
1388 mono_defaults.uint32_class = mono_class_from_name (
1389 mono_defaults.corlib, "System", "UInt32");
1390 g_assert (mono_defaults.uint32_class != 0);
1392 mono_defaults.uint_class = mono_class_from_name (
1393 mono_defaults.corlib, "System", "UIntPtr");
1394 g_assert (mono_defaults.uint_class != 0);
1396 mono_defaults.int_class = mono_class_from_name (
1397 mono_defaults.corlib, "System", "IntPtr");
1398 g_assert (mono_defaults.int_class != 0);
1400 mono_defaults.int64_class = mono_class_from_name (
1401 mono_defaults.corlib, "System", "Int64");
1402 g_assert (mono_defaults.int64_class != 0);
1404 mono_defaults.uint64_class = mono_class_from_name (
1405 mono_defaults.corlib, "System", "UInt64");
1406 g_assert (mono_defaults.uint64_class != 0);
1408 mono_defaults.single_class = mono_class_from_name (
1409 mono_defaults.corlib, "System", "Single");
1410 g_assert (mono_defaults.single_class != 0);
1412 mono_defaults.double_class = mono_class_from_name (
1413 mono_defaults.corlib, "System", "Double");
1414 g_assert (mono_defaults.double_class != 0);
1416 mono_defaults.char_class = mono_class_from_name (
1417 mono_defaults.corlib, "System", "Char");
1418 g_assert (mono_defaults.char_class != 0);
1420 mono_defaults.string_class = mono_class_from_name (
1421 mono_defaults.corlib, "System", "String");
1422 g_assert (mono_defaults.string_class != 0);
1424 mono_defaults.enum_class = mono_class_from_name (
1425 mono_defaults.corlib, "System", "Enum");
1426 g_assert (mono_defaults.enum_class != 0);
1428 mono_defaults.array_class = mono_class_from_name (
1429 mono_defaults.corlib, "System", "Array");
1430 g_assert (mono_defaults.array_class != 0);
1432 mono_defaults.delegate_class = mono_class_from_name (
1433 mono_defaults.corlib, "System", "Delegate");
1434 g_assert (mono_defaults.delegate_class != 0 );
1436 mono_defaults.multicastdelegate_class = mono_class_from_name (
1437 mono_defaults.corlib, "System", "MulticastDelegate");
1438 g_assert (mono_defaults.multicastdelegate_class != 0 );
1440 mono_defaults.asyncresult_class = mono_class_from_name (
1441 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1443 g_assert (mono_defaults.asyncresult_class != 0 );
1445 mono_defaults.waithandle_class = mono_class_from_name (
1446 mono_defaults.corlib, "System.Threading", "WaitHandle");
1447 g_assert (mono_defaults.waithandle_class != 0 );
1449 mono_defaults.typehandle_class = mono_class_from_name (
1450 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1451 g_assert (mono_defaults.typehandle_class != 0);
1453 mono_defaults.methodhandle_class = mono_class_from_name (
1454 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1455 g_assert (mono_defaults.methodhandle_class != 0);
1457 mono_defaults.fieldhandle_class = mono_class_from_name (
1458 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1459 g_assert (mono_defaults.fieldhandle_class != 0);
1461 mono_defaults.systemtype_class = mono_class_from_name (
1462 mono_defaults.corlib, "System", "Type");
1463 g_assert (mono_defaults.systemtype_class != 0);
1465 mono_defaults.monotype_class = mono_class_from_name (
1466 mono_defaults.corlib, "System", "MonoType");
1467 g_assert (mono_defaults.monotype_class != 0);
1469 mono_defaults.exception_class = mono_class_from_name (
1470 mono_defaults.corlib, "System", "Exception");
1471 g_assert (mono_defaults.exception_class != 0);
1473 mono_defaults.threadabortexception_class = mono_class_from_name (
1474 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1475 g_assert (mono_defaults.threadabortexception_class != 0);
1477 mono_defaults.thread_class = mono_class_from_name (
1478 mono_defaults.corlib, "System.Threading", "Thread");
1479 g_assert (mono_defaults.thread_class != 0);
1481 mono_defaults.appdomain_class = mono_class_from_name (
1482 mono_defaults.corlib, "System", "AppDomain");
1483 g_assert (mono_defaults.appdomain_class != 0);
1485 mono_defaults.transparent_proxy_class = mono_class_from_name (
1486 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1487 g_assert (mono_defaults.transparent_proxy_class != 0);
1489 mono_defaults.real_proxy_class = mono_class_from_name (
1490 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1491 g_assert (mono_defaults.real_proxy_class != 0);
1493 mono_defaults.mono_method_message_class = mono_class_from_name (
1494 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1495 g_assert (mono_defaults.mono_method_message_class != 0);
1497 mono_defaults.field_info_class = mono_class_from_name (
1498 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1499 g_assert (mono_defaults.field_info_class != 0);
1501 mono_defaults.method_info_class = mono_class_from_name (
1502 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1503 g_assert (mono_defaults.method_info_class != 0);
1505 mono_defaults.stringbuilder_class = mono_class_from_name (
1506 mono_defaults.corlib, "System.Text", "StringBuilder");
1507 g_assert (mono_defaults.stringbuilder_class != 0);
1509 mono_defaults.math_class = mono_class_from_name (
1510 mono_defaults.corlib, "System", "Math");
1511 g_assert (mono_defaults.math_class != 0);
1513 mono_defaults.stack_frame_class = mono_class_from_name (
1514 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1515 g_assert (mono_defaults.stack_frame_class != 0);
1517 mono_defaults.stack_trace_class = mono_class_from_name (
1518 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1519 g_assert (mono_defaults.stack_trace_class != 0);
1521 mono_defaults.marshal_class = mono_class_from_name (
1522 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1523 g_assert (mono_defaults.marshal_class != 0);
1525 mono_defaults.iserializeable_class = mono_class_from_name (
1526 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1527 g_assert (mono_defaults.iserializeable_class != 0);
1529 mono_defaults.serializationinfo_class = mono_class_from_name (
1530 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1531 g_assert (mono_defaults.serializationinfo_class != 0);
1533 mono_defaults.streamingcontext_class = mono_class_from_name (
1534 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1535 g_assert (mono_defaults.streamingcontext_class != 0);
1537 mono_defaults.typed_reference_class = mono_class_from_name (
1538 mono_defaults.corlib, "System", "TypedReference");
1539 g_assert (mono_defaults.typed_reference_class != 0);
1541 mono_defaults.argumenthandle_class = mono_class_from_name (
1542 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1543 g_assert (mono_defaults.argumenthandle_class != 0);
1545 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1546 mono_defaults.corlib, "System", "MarshalByRefObject");
1547 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1549 mono_defaults.monitor_class = mono_class_from_name (
1550 mono_defaults.corlib, "System.Threading", "Monitor");
1551 g_assert (mono_defaults.monitor_class != 0);
1553 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1554 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1555 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1557 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1558 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1560 mono_defaults.executioncontext_class = mono_class_from_name (
1561 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1563 mono_defaults.internals_visible_class = mono_class_from_name (
1564 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1566 mono_defaults.critical_finalizer_object = mono_class_from_name (
1567 mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
1570 * mscorlib needs a little help, only now it can load its friends list (after we have
1571 * loaded the InternalsVisibleToAttribute), load it now
1573 mono_assembly_load_friends (ass);
1575 mono_defaults.safehandle_class = mono_class_from_name (
1576 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1578 mono_defaults.handleref_class = mono_class_from_name (
1579 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1581 mono_defaults.attribute_class = mono_class_from_name (
1582 mono_defaults.corlib, "System", "Attribute");
1584 mono_defaults.customattribute_data_class = mono_class_from_name (
1585 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1587 /* these are initialized lazily when COM features are used */
1588 mono_defaults.variant_class = NULL;
1589 mono_defaults.com_object_class = NULL;
1590 mono_defaults.com_interop_proxy_class = NULL;
1591 mono_defaults.iunknown_class = NULL;
1592 mono_defaults.idispatch_class = NULL;
1595 * Note that mono_defaults.generic_*_class is only non-NULL if we're
1596 * using the 2.0 corlib.
1598 mono_class_init (mono_defaults.array_class);
1599 mono_defaults.generic_nullable_class = mono_class_from_name (
1600 mono_defaults.corlib, "System", "Nullable`1");
1601 mono_defaults.generic_ilist_class = mono_class_from_name (
1602 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1604 domain->friendly_name = g_path_get_basename (filename);
1606 _mono_debug_init_corlib (domain);
1614 * Creates the initial application domain and initializes the mono_defaults
1616 * This function is guaranteed to not run any IL code.
1617 * The runtime is initialized using the default runtime version.
1619 * Returns: the initial domain.
1622 mono_init (const char *domain_name)
1624 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1628 * mono_init_from_assembly:
1630 * Creates the initial application domain and initializes the mono_defaults
1632 * This function is guaranteed to not run any IL code.
1633 * The runtime is initialized using the runtime version required by the
1634 * provided executable. The version is determined by looking at the exe
1635 * configuration file and the version PE field)
1637 * Returns: the initial domain.
1640 mono_init_from_assembly (const char *domain_name, const char *filename)
1642 return mono_init_internal (domain_name, filename, NULL);
1646 * mono_init_version:
1648 * Creates the initial application domain and initializes the mono_defaults
1650 * This function is guaranteed to not run any IL code.
1651 * The runtime is initialized using the provided rutime version.
1653 * Returns: the initial domain.
1656 mono_init_version (const char *domain_name, const char *version)
1658 return mono_init_internal (domain_name, NULL, version);
1662 * mono_init_com_types:
1664 * Initializes all types needed for COM Interop in mono_defaults structure.
1667 mono_init_com_types (void)
1669 static gboolean initialized = FALSE;
1674 /* FIXME: do I need some threading protection here */
1676 g_assert (mono_defaults.corlib);
1678 mono_defaults.variant_class = mono_class_from_name (
1679 mono_defaults.corlib, "System", "Variant");
1680 g_assert (mono_defaults.variant_class != 0);
1682 mono_defaults.com_object_class = mono_class_from_name (
1683 mono_defaults.corlib, "System", "__ComObject");
1684 g_assert (mono_defaults.com_object_class != 0);
1686 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1687 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1688 g_assert (mono_defaults.com_interop_proxy_class != 0);
1690 mono_defaults.iunknown_class = mono_class_from_name (
1691 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1692 g_assert (mono_defaults.iunknown_class != 0);
1694 mono_defaults.idispatch_class = mono_class_from_name (
1695 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1696 g_assert (mono_defaults.idispatch_class != 0);
1704 * Cleans up all metadata modules.
1709 mono_close_exe_image ();
1711 mono_loader_cleanup ();
1712 mono_classes_cleanup ();
1713 mono_assemblies_cleanup ();
1714 mono_images_cleanup ();
1715 mono_debug_cleanup ();
1716 mono_metadata_cleanup ();
1718 TlsFree (appdomain_thread_id);
1719 DeleteCriticalSection (&appdomains_mutex);
1723 mono_close_exe_image (void)
1726 mono_image_close (exe_image);
1730 * mono_get_root_domain:
1732 * The root AppDomain is the initial domain created by the runtime when it is
1733 * initialized. Programs execute on this AppDomain, but can create new ones
1734 * later. Currently there is no unmanaged API to create new AppDomains, this
1735 * must be done from managed code.
1737 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1740 mono_get_root_domain (void)
1742 return mono_root_domain;
1748 * Returns: the current domain, to obtain the root domain use
1749 * mono_get_root_domain().
1754 return GET_APPDOMAIN ();
1758 * mono_domain_set_internal:
1759 * @domain: the new domain
1761 * Sets the current domain to @domain.
1764 mono_domain_set_internal (MonoDomain *domain)
1766 SET_APPDOMAIN (domain);
1767 SET_APPCONTEXT (domain->default_context);
1771 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1777 * Create a copy of the data to avoid calling the user callback
1778 * inside the lock because that could lead to deadlocks.
1779 * We can do this because this function is not perf. critical.
1781 mono_appdomains_lock ();
1782 size = appdomain_list_size;
1783 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1784 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1785 mono_appdomains_unlock ();
1787 for (i = 0; i < size; ++i) {
1789 func (copy [i], user_data);
1792 mono_gc_free_fixed (copy);
1796 * mono_domain_assembly_open:
1797 * @domain: the application domain
1798 * @name: file name of the assembly
1800 * fixme: maybe we should integrate this with mono_assembly_open ??
1803 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1808 mono_domain_assemblies_lock (domain);
1809 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1811 if (strcmp (name, ass->aname.name) == 0) {
1812 mono_domain_assemblies_unlock (domain);
1816 mono_domain_assemblies_unlock (domain);
1818 if (!(ass = mono_assembly_open (name, NULL)))
1825 free_slist (gpointer key, gpointer value, gpointer user_data)
1827 g_slist_free (value);
1831 mono_domain_free (MonoDomain *domain, gboolean force)
1833 int code_size, code_alloc;
1835 if ((domain == mono_root_domain) && !force) {
1836 g_warning ("cant unload root domain");
1840 if (mono_dont_free_domains)
1843 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1845 if (free_domain_hook)
1846 free_domain_hook (domain);
1848 mono_debug_domain_unload (domain);
1850 mono_appdomains_lock ();
1851 appdomains_list [domain->domain_id] = NULL;
1852 mono_appdomains_unlock ();
1854 /* FIXME: free delegate_hash_table when it's used */
1855 if (domain->search_path) {
1856 g_strfreev (domain->search_path);
1857 domain->search_path = NULL;
1859 domain->create_proxy_for_type_method = NULL;
1860 domain->private_invoke_method = NULL;
1861 domain->default_context = NULL;
1862 domain->out_of_memory_ex = NULL;
1863 domain->null_reference_ex = NULL;
1864 domain->stack_overflow_ex = NULL;
1865 domain->entry_assembly = NULL;
1866 /* must do this early as it accesses fields and types */
1867 if (domain->special_static_fields) {
1868 mono_alloc_special_static_data_free (domain->special_static_fields);
1869 g_hash_table_destroy (domain->special_static_fields);
1870 domain->special_static_fields = NULL;
1872 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1873 MonoAssembly *ass = tmp->data;
1874 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s %p, assembly %s %p, refcount=%d\n", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count);
1875 mono_assembly_close (ass);
1877 g_slist_free (domain->domain_assemblies);
1878 domain->domain_assemblies = NULL;
1880 g_free (domain->friendly_name);
1881 domain->friendly_name = NULL;
1882 mono_g_hash_table_destroy (domain->env);
1884 g_hash_table_destroy (domain->class_vtable_hash);
1885 domain->class_vtable_hash = NULL;
1886 g_hash_table_destroy (domain->proxy_vtable_hash);
1887 domain->proxy_vtable_hash = NULL;
1888 if (domain->static_data_array) {
1889 mono_gc_free_fixed (domain->static_data_array);
1890 domain->static_data_array = NULL;
1892 mono_internal_hash_table_destroy (&domain->jit_code_hash);
1893 mono_g_hash_table_destroy (domain->ldstr_table);
1894 domain->ldstr_table = NULL;
1897 * There might still be jit info tables of this domain which
1898 * are not freed. Since the domain cannot be in use anymore,
1899 * this will free them.
1901 mono_thread_hazardous_try_free_all ();
1902 g_assert (domain->num_jit_info_tables == 1);
1903 jit_info_table_free (domain->jit_info_table);
1904 domain->jit_info_table = NULL;
1905 g_assert (!domain->jit_info_free_queue);
1907 /* collect statistics */
1908 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
1909 total_domain_code_alloc += code_alloc;
1910 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
1911 max_domain_code_size = MAX (max_domain_code_size, code_size);
1913 #ifdef DEBUG_DOMAIN_UNLOAD
1914 mono_mempool_invalidate (domain->mp);
1915 mono_code_manager_invalidate (domain->code_mp);
1917 mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
1918 mono_mempool_destroy (domain->mp);
1920 mono_code_manager_destroy (domain->code_mp);
1921 domain->code_mp = NULL;
1923 if (domain->type_hash) {
1924 mono_g_hash_table_destroy (domain->type_hash);
1925 domain->type_hash = NULL;
1927 if (domain->refobject_hash) {
1928 mono_g_hash_table_destroy (domain->refobject_hash);
1929 domain->refobject_hash = NULL;
1931 if (domain->type_init_exception_hash) {
1932 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1933 domain->type_init_exception_hash = NULL;
1935 g_hash_table_destroy (domain->finalizable_objects_hash);
1936 domain->finalizable_objects_hash = NULL;
1937 if (domain->track_resurrection_objects_hash) {
1938 g_hash_table_foreach (domain->track_resurrection_objects_hash, free_slist, NULL);
1939 g_hash_table_destroy (domain->track_resurrection_objects_hash);
1941 if (domain->track_resurrection_handles_hash)
1942 g_hash_table_destroy (domain->track_resurrection_handles_hash);
1943 if (domain->method_rgctx_hash) {
1944 g_hash_table_destroy (domain->method_rgctx_hash);
1945 domain->method_rgctx_hash = NULL;
1947 if (domain->generic_virtual_cases) {
1948 g_hash_table_destroy (domain->generic_virtual_cases);
1949 domain->generic_virtual_cases = NULL;
1952 DeleteCriticalSection (&domain->finalizable_objects_hash_lock);
1953 DeleteCriticalSection (&domain->assemblies_lock);
1954 DeleteCriticalSection (&domain->jit_code_hash_lock);
1955 DeleteCriticalSection (&domain->lock);
1956 domain->setup = NULL;
1958 /* FIXME: anything else required ? */
1960 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
1962 mono_gc_free_fixed (domain);
1964 mono_perfcounters->loader_appdomains--;
1966 if ((domain == mono_root_domain))
1967 mono_root_domain = NULL;
1971 * mono_domain_get_id:
1974 * Returns: the a domain for a specific domain id.
1977 mono_domain_get_by_id (gint32 domainid)
1979 MonoDomain * domain;
1981 mono_appdomains_lock ();
1982 if (domainid < appdomain_list_size)
1983 domain = appdomains_list [domainid];
1986 mono_appdomains_unlock ();
1992 mono_domain_get_id (MonoDomain *domain)
1994 return domain->domain_id;
1998 * mono_domain_alloc:
2000 * LOCKING: Acquires the domain lock.
2003 mono_domain_alloc (MonoDomain *domain, guint size)
2007 mono_domain_lock (domain);
2008 mono_perfcounters->loader_bytes += size;
2009 res = mono_mempool_alloc (domain->mp, size);
2010 mono_domain_unlock (domain);
2016 * mono_domain_alloc0:
2018 * LOCKING: Acquires the domain lock.
2021 mono_domain_alloc0 (MonoDomain *domain, guint size)
2025 mono_domain_lock (domain);
2026 mono_perfcounters->loader_bytes += size;
2027 res = mono_mempool_alloc0 (domain->mp, size);
2028 mono_domain_unlock (domain);
2034 * mono_domain_code_reserve:
2036 * LOCKING: Acquires the domain lock.
2039 mono_domain_code_reserve (MonoDomain *domain, int size)
2043 mono_domain_lock (domain);
2044 res = mono_code_manager_reserve (domain->code_mp, size);
2045 mono_domain_unlock (domain);
2051 * mono_domain_code_reserve_align:
2053 * LOCKING: Acquires the domain lock.
2056 mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment)
2060 mono_domain_lock (domain);
2061 res = mono_code_manager_reserve_align (domain->code_mp, size, alignment);
2062 mono_domain_unlock (domain);
2068 * mono_domain_code_commit:
2070 * LOCKING: Acquires the domain lock.
2073 mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize)
2075 mono_domain_lock (domain);
2076 mono_code_manager_commit (domain->code_mp, data, size, newsize);
2077 mono_domain_unlock (domain);
2081 * mono_domain_code_foreach:
2082 * Iterate over the code thunks of the code manager of @domain.
2084 * The @func callback MUST not take any locks. If it really needs to, it must respect
2085 * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety
2086 * LOCKING: Acquires the domain lock.
2090 mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data)
2092 mono_domain_lock (domain);
2093 mono_code_manager_foreach (domain->code_mp, func, user_data);
2094 mono_domain_unlock (domain);
2099 mono_context_set (MonoAppContext * new_context)
2101 SET_APPCONTEXT (new_context);
2105 mono_context_get (void)
2107 return GET_APPCONTEXT ();
2110 /* LOCKING: the caller holds the lock for this domain */
2112 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
2114 /* The first entry in the array is the index of the next free slot
2115 * and the total size of the array
2118 if (domain->static_data_array) {
2119 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
2120 next = GPOINTER_TO_INT (domain->static_data_array [0]);
2122 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), NULL);
2123 memcpy (new_array, domain->static_data_array, sizeof (gpointer) * size);
2125 new_array [1] = GINT_TO_POINTER (size);
2126 mono_gc_free_fixed (domain->static_data_array);
2127 domain->static_data_array = new_array;
2131 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, NULL);
2133 new_array [0] = GINT_TO_POINTER (next);
2134 new_array [1] = GINT_TO_POINTER (size);
2135 domain->static_data_array = new_array;
2137 domain->static_data_array [next++] = data;
2138 domain->static_data_array [0] = GINT_TO_POINTER (next);
2142 mono_get_corlib (void)
2144 return mono_defaults.corlib;
2148 mono_get_object_class (void)
2150 return mono_defaults.object_class;
2154 mono_get_byte_class (void)
2156 return mono_defaults.byte_class;
2160 mono_get_void_class (void)
2162 return mono_defaults.void_class;
2166 mono_get_boolean_class (void)
2168 return mono_defaults.boolean_class;
2172 mono_get_sbyte_class (void)
2174 return mono_defaults.sbyte_class;
2178 mono_get_int16_class (void)
2180 return mono_defaults.int16_class;
2184 mono_get_uint16_class (void)
2186 return mono_defaults.uint16_class;
2190 mono_get_int32_class (void)
2192 return mono_defaults.int32_class;
2196 mono_get_uint32_class (void)
2198 return mono_defaults.uint32_class;
2202 mono_get_intptr_class (void)
2204 return mono_defaults.int_class;
2208 mono_get_uintptr_class (void)
2210 return mono_defaults.uint_class;
2214 mono_get_int64_class (void)
2216 return mono_defaults.int64_class;
2220 mono_get_uint64_class (void)
2222 return mono_defaults.uint64_class;
2226 mono_get_single_class (void)
2228 return mono_defaults.single_class;
2232 mono_get_double_class (void)
2234 return mono_defaults.double_class;
2238 mono_get_char_class (void)
2240 return mono_defaults.char_class;
2244 mono_get_string_class (void)
2246 return mono_defaults.string_class;
2250 mono_get_enum_class (void)
2252 return mono_defaults.enum_class;
2256 mono_get_array_class (void)
2258 return mono_defaults.array_class;
2262 mono_get_thread_class (void)
2264 return mono_defaults.thread_class;
2268 mono_get_exception_class (void)
2270 return mono_defaults.exception_class;
2274 static char* get_attribute_value (const gchar **attribute_names,
2275 const gchar **attribute_values,
2276 const char *att_name)
2279 for (n=0; attribute_names[n] != NULL; n++) {
2280 if (strcmp (attribute_names[n], att_name) == 0)
2281 return g_strdup (attribute_values[n]);
2286 static void start_element (GMarkupParseContext *context,
2287 const gchar *element_name,
2288 const gchar **attribute_names,
2289 const gchar **attribute_values,
2293 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2295 if (strcmp (element_name, "configuration") == 0) {
2296 app_config->configuration_count++;
2299 if (strcmp (element_name, "startup") == 0) {
2300 app_config->startup_count++;
2304 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2307 if (strcmp (element_name, "requiredRuntime") == 0) {
2308 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2309 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2310 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2311 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2315 static void end_element (GMarkupParseContext *context,
2316 const gchar *element_name,
2320 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2322 if (strcmp (element_name, "configuration") == 0) {
2323 app_config->configuration_count--;
2324 } else if (strcmp (element_name, "startup") == 0) {
2325 app_config->startup_count--;
2329 static const GMarkupParser
2338 static AppConfigInfo *
2339 app_config_parse (const char *exe_filename)
2341 AppConfigInfo *app_config;
2342 GMarkupParseContext *context;
2345 const char *bundled_config;
2346 char *config_filename;
2348 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2350 if (bundled_config) {
2351 text = g_strdup (bundled_config);
2352 len = strlen (text);
2354 config_filename = g_strconcat (exe_filename, ".config", NULL);
2356 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2357 g_free (config_filename);
2360 g_free (config_filename);
2363 app_config = g_new0 (AppConfigInfo, 1);
2365 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2366 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2367 g_markup_parse_context_end_parse (context, NULL);
2369 g_markup_parse_context_free (context);
2375 app_config_free (AppConfigInfo* app_config)
2378 GSList *list = app_config->supported_runtimes;
2379 while (list != NULL) {
2380 rt = (char*)list->data;
2382 list = g_slist_next (list);
2384 g_slist_free (app_config->supported_runtimes);
2385 g_free (app_config->required_runtime);
2386 g_free (app_config);
2390 static const MonoRuntimeInfo*
2391 get_runtime_by_version (const char *version)
2394 int max = G_N_ELEMENTS (supported_runtimes);
2396 for (n=0; n<max; n++) {
2397 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2398 return &supported_runtimes[n];
2404 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2406 AppConfigInfo* app_config;
2408 const MonoRuntimeInfo* runtime = NULL;
2409 MonoImage *image = NULL;
2411 app_config = app_config_parse (exe_file);
2413 if (app_config != NULL) {
2414 /* Check supportedRuntime elements, if none is supported, fail.
2415 * If there are no such elements, look for a requiredRuntime element.
2417 if (app_config->supported_runtimes != NULL) {
2419 GSList *list = app_config->supported_runtimes;
2420 while (list != NULL) {
2421 version = (char*) list->data;
2422 runtime = get_runtime_by_version (version);
2423 if (runtime != NULL)
2424 runtimes [n++] = runtime;
2425 list = g_slist_next (list);
2427 runtimes [n] = NULL;
2428 app_config_free (app_config);
2432 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2433 if (app_config->required_runtime != NULL) {
2434 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2435 runtimes [1] = NULL;
2436 app_config_free (app_config);
2439 app_config_free (app_config);
2442 /* Look for a runtime with the exact version */
2443 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2446 image = mono_image_open (exe_file, NULL);
2448 if (image == NULL) {
2449 /* The image is wrong or the file was not found. In this case return
2450 * a default runtime and leave to the initialization method the work of
2451 * reporting the error.
2453 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2454 runtimes [1] = NULL;
2460 runtimes [0] = get_runtime_by_version (image->version);
2461 runtimes [1] = NULL;
2466 * mono_get_runtime_info:
2468 * Returns: the version of the current runtime instance.
2470 const MonoRuntimeInfo*
2471 mono_get_runtime_info (void)
2473 return current_runtime;
2477 mono_debugger_check_runtime_version (const char *filename)
2479 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2480 const MonoRuntimeInfo *rinfo;
2483 get_runtimes_from_exe (filename, &image, runtimes);
2484 rinfo = runtimes [0];
2487 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2489 if (rinfo != current_runtime)
2490 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2491 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2492 filename, rinfo->runtime_version);
2498 * mono_framework_version:
2500 * Return the major version of the framework curently executing.
2503 mono_framework_version (void)
2505 return current_runtime->framework_version [0] - '0';