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-internal.h>
21 #include <mono/utils/mono-membar.h>
22 #include <mono/utils/mono-counters.h>
23 #include <mono/utils/hazard-pointer.h>
24 #include <mono/utils/mono-tls.h>
25 #include <mono/metadata/object.h>
26 #include <mono/metadata/object-internals.h>
27 #include <mono/metadata/domain-internals.h>
28 #include <mono/metadata/class-internals.h>
29 #include <mono/metadata/assembly.h>
30 #include <mono/metadata/exception.h>
31 #include <mono/metadata/metadata-internals.h>
32 #include <mono/metadata/gc-internal.h>
33 #include <mono/metadata/appdomain.h>
34 #include <mono/metadata/mono-debug-debugger.h>
35 #include <mono/metadata/mono-config.h>
36 #include <mono/metadata/threads-types.h>
37 #include <metadata/threads.h>
38 #include <metadata/profiler-private.h>
39 #include <mono/metadata/coree.h>
41 /* #define DEBUG_DOMAIN_UNLOAD */
43 /* we need to use both the Tls* functions and __thread because
44 * some archs may generate faster jit code with one meachanism
45 * or the other (we used to do it because tls slots were GC-tracked,
46 * but we can't depend on this).
48 static MonoNativeTlsKey appdomain_thread_id;
50 #ifdef MONO_HAVE_FAST_TLS
52 MONO_FAST_TLS_DECLARE(tls_appdomain);
54 #define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain))
56 #define SET_APPDOMAIN(x) do { \
57 MONO_FAST_TLS_SET (tls_appdomain,x); \
58 mono_native_tls_set_value (appdomain_thread_id, x); \
61 #else /* !MONO_HAVE_FAST_TLS */
63 #define GET_APPDOMAIN() ((MonoDomain *)mono_native_tls_get_value (appdomain_thread_id))
64 #define SET_APPDOMAIN(x) mono_native_tls_set_value (appdomain_thread_id, x);
68 #define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext)
69 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x))
71 static guint16 appdomain_list_size = 0;
72 static guint16 appdomain_next = 0;
73 static MonoDomain **appdomains_list = NULL;
74 static MonoImage *exe_image;
76 gboolean mono_dont_free_domains;
78 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
79 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
80 static CRITICAL_SECTION appdomains_mutex;
82 static MonoDomain *mono_root_domain = NULL;
85 static int max_domain_code_size = 0;
86 static int max_domain_code_alloc = 0;
87 static int total_domain_code_alloc = 0;
89 /* AppConfigInfo: Information about runtime versions supported by an
93 GSList *supported_runtimes;
94 char *required_runtime;
95 int configuration_count;
100 * AotModuleInfo: Contains information about AOT modules.
107 static const MonoRuntimeInfo *current_runtime = NULL;
109 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
112 * Contains information about AOT loaded code.
114 static MonoAotModuleInfoTable *aot_modules = NULL;
116 /* This is the list of runtime versions supported by this JIT.
118 static const MonoRuntimeInfo supported_runtimes[] = {
119 {"v2.0.50215","2.0", { {2,0,0,0}, {8,0,0,0}, { 3, 5, 0, 0 } } },
120 {"v2.0.50727","2.0", { {2,0,0,0}, {8,0,0,0}, { 3, 5, 0, 0 } } },
121 {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } },
122 {"v4.0.30128","4.0", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } },
123 {"v4.0.30319","4.0", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } },
124 {"moonlight", "2.1", { {2,0,5,0}, {9,0,0,0}, { 3, 5, 0, 0 } } },
128 /* The stable runtime version */
129 #define DEFAULT_RUNTIME_VERSION "v2.0.50727"
131 /* Callbacks installed by the JIT */
132 static MonoCreateDomainFunc create_domain_hook;
133 static MonoFreeDomainFunc free_domain_hook;
135 /* This is intentionally not in the header file, so people don't misuse it. */
136 extern void _mono_debug_init_corlib (MonoDomain *domain);
139 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
141 static const MonoRuntimeInfo*
142 get_runtime_by_version (const char *version);
145 mono_jit_info_find_aot_module (guint8* addr);
148 mono_domain_get_tls_key (void)
150 return appdomain_thread_id;
154 mono_domain_get_tls_offset (void)
157 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
158 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
163 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
164 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
165 #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)
167 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
168 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
170 #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
171 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
173 #define JIT_INFO_TABLE_HAZARD_INDEX 0
174 #define JIT_INFO_HAZARD_INDEX 1
177 jit_info_table_num_elements (MonoJitInfoTable *table)
180 int num_elements = 0;
182 for (i = 0; i < table->num_chunks; ++i) {
183 MonoJitInfoTableChunk *chunk = table->chunks [i];
184 int chunk_num_elements = chunk->num_elements;
187 for (j = 0; j < chunk_num_elements; ++j) {
188 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
196 static MonoJitInfoTableChunk*
197 jit_info_table_new_chunk (void)
199 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
205 static MonoJitInfoTable *
206 jit_info_table_new (MonoDomain *domain)
208 MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
210 table->domain = domain;
211 table->num_chunks = 1;
212 table->chunks [0] = jit_info_table_new_chunk ();
218 jit_info_table_free (MonoJitInfoTable *table)
221 int num_chunks = table->num_chunks;
222 MonoDomain *domain = table->domain;
224 mono_domain_lock (domain);
226 table->domain->num_jit_info_tables--;
227 if (table->domain->num_jit_info_tables <= 1) {
230 for (list = table->domain->jit_info_free_queue; list; list = list->next)
233 g_slist_free (table->domain->jit_info_free_queue);
234 table->domain->jit_info_free_queue = NULL;
237 /* At this point we assume that there are no other threads
238 still accessing the table, so we don't have to worry about
239 hazardous pointers. */
241 for (i = 0; i < num_chunks; ++i) {
242 MonoJitInfoTableChunk *chunk = table->chunks [i];
246 if (--chunk->refcount > 0)
249 num_elements = chunk->num_elements;
250 for (j = 0; j < num_elements; ++j) {
251 MonoJitInfo *ji = chunk->data [j];
253 if (IS_JIT_INFO_TOMBSTONE (ji))
260 mono_domain_unlock (domain);
265 /* The jit_info_table is sorted in ascending order by the end
266 * addresses of the compiled methods. The reason why we have to do
267 * this is that once we introduce tombstones, it becomes possible for
268 * code ranges to overlap, and if we sort by code start and insert at
269 * the back of the table, we cannot guarantee that we won't overlook
272 * There are actually two possible ways to do the sorting and
273 * inserting which work with our lock-free mechanism:
275 * 1. Sort by start address and insert at the front. When looking for
276 * an entry, find the last one with a start address lower than the one
277 * you're looking for, then work your way to the front of the table.
279 * 2. Sort by end address and insert at the back. When looking for an
280 * entry, find the first one with an end address higher than the one
281 * you're looking for, then work your way to the end of the table.
283 * We chose the latter out of convenience.
286 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
288 int left = 0, right = table->num_chunks;
290 g_assert (left < right);
293 int pos = (left + right) / 2;
294 MonoJitInfoTableChunk *chunk = table->chunks [pos];
296 if (addr < chunk->last_code_end)
300 } while (left < right);
301 g_assert (left == right);
303 if (left >= table->num_chunks)
304 return table->num_chunks - 1;
309 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
311 int left = 0, right = chunk->num_elements;
313 while (left < right) {
314 int pos = (left + right) / 2;
315 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
316 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
323 g_assert (left == right);
329 mono_jit_info_table_find (MonoDomain *domain, char *addr)
331 MonoJitInfoTable *table;
334 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
337 ++mono_stats.jit_info_table_lookup_count;
339 /* First we have to get the domain's jit_info_table. This is
340 complicated by the fact that a writer might substitute a
341 new table and free the old one. What the writer guarantees
342 us is that it looks at the hazard pointers after it has
343 changed the jit_info_table pointer. So, if we guard the
344 table by a hazard pointer and make sure that the pointer is
345 still there after we've made it hazardous, we don't have to
346 worry about the writer freeing the table. */
347 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
349 chunk_pos = jit_info_table_index (table, (gint8*)addr);
350 g_assert (chunk_pos < table->num_chunks);
352 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
354 /* We now have a position that's very close to that of the
355 first element whose end address is higher than the one
356 we're looking for. If we don't have the exact position,
357 then we have a position below that one, so we'll just
358 search upward until we find our element. */
360 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
362 while (pos < chunk->num_elements) {
363 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
367 if (IS_JIT_INFO_TOMBSTONE (ji)) {
368 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
371 if ((gint8*)addr >= (gint8*)ji->code_start
372 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
373 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
374 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
378 /* If we find a non-tombstone element which is already
379 beyond what we're looking for, we have to end the
381 if ((gint8*)addr < (gint8*)ji->code_start)
387 } while (chunk_pos < table->num_chunks);
393 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
394 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
398 /* Maybe its an AOT module */
399 image = mono_jit_info_find_aot_module ((guint8*)addr);
401 ji = jit_info_find_in_aot_func (domain, image, addr);
406 static G_GNUC_UNUSED void
407 jit_info_table_check (MonoJitInfoTable *table)
411 for (i = 0; i < table->num_chunks; ++i) {
412 MonoJitInfoTableChunk *chunk = table->chunks [i];
415 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
416 if (chunk->refcount > 10)
417 printf("warning: chunk refcount is %d\n", chunk->refcount);
418 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
420 for (j = 0; j < chunk->num_elements; ++j) {
421 MonoJitInfo *this = chunk->data [j];
424 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
426 if (j < chunk->num_elements - 1)
427 next = chunk->data [j + 1];
428 else if (i < table->num_chunks - 1) {
431 for (k = i + 1; k < table->num_chunks; ++k)
432 if (table->chunks [k]->num_elements > 0)
435 if (k >= table->num_chunks)
438 g_assert (table->chunks [k]->num_elements > 0);
439 next = table->chunks [k]->data [0];
443 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
448 static MonoJitInfoTable*
449 jit_info_table_realloc (MonoJitInfoTable *old)
452 int num_elements = jit_info_table_num_elements (old);
455 int new_chunk, new_element;
456 MonoJitInfoTable *new;
458 /* number of needed places for elements needed */
459 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
460 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
462 new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
463 new->domain = old->domain;
464 new->num_chunks = num_chunks;
466 for (i = 0; i < num_chunks; ++i)
467 new->chunks [i] = jit_info_table_new_chunk ();
471 for (i = 0; i < old->num_chunks; ++i) {
472 MonoJitInfoTableChunk *chunk = old->chunks [i];
473 int chunk_num_elements = chunk->num_elements;
476 for (j = 0; j < chunk_num_elements; ++j) {
477 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
478 g_assert (new_chunk < num_chunks);
479 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
480 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
481 new->chunks [new_chunk]->num_elements = new_element;
489 if (new_chunk < num_chunks) {
490 g_assert (new_chunk == num_chunks - 1);
491 new->chunks [new_chunk]->num_elements = new_element;
492 g_assert (new->chunks [new_chunk]->num_elements > 0);
495 for (i = 0; i < num_chunks; ++i) {
496 MonoJitInfoTableChunk *chunk = new->chunks [i];
497 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
499 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
506 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
508 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
509 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
511 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
513 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
514 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
516 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
517 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
519 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
520 + new1->data [new1->num_elements - 1]->code_size;
521 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
522 + new2->data [new2->num_elements - 1]->code_size;
528 static MonoJitInfoTable*
529 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
531 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
532 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
535 new_table->domain = table->domain;
536 new_table->num_chunks = table->num_chunks + 1;
539 for (i = 0; i < table->num_chunks; ++i) {
540 if (table->chunks [i] == chunk) {
541 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
544 new_table->chunks [j] = table->chunks [i];
545 ++new_table->chunks [j]->refcount;
550 g_assert (j == new_table->num_chunks);
555 static MonoJitInfoTableChunk*
556 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
558 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
562 for (i = 0; i < old->num_elements; ++i) {
563 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
564 new->data [j++] = old->data [i];
567 new->num_elements = j;
568 if (new->num_elements > 0)
569 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
571 new->last_code_end = old->last_code_end;
576 static MonoJitInfoTable*
577 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
579 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
580 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
583 new_table->domain = table->domain;
584 new_table->num_chunks = table->num_chunks;
587 for (i = 0; i < table->num_chunks; ++i) {
588 if (table->chunks [i] == chunk)
589 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
591 new_table->chunks [j] = table->chunks [i];
592 ++new_table->chunks [j]->refcount;
597 g_assert (j == new_table->num_chunks);
602 /* As we add an element to the table the case can arise that the chunk
603 * to which we need to add is already full. In that case we have to
604 * allocate a new table and do something about that chunk. We have
605 * several strategies:
607 * If the number of elements in the table is below the low watermark
608 * or above the high watermark, we reallocate the whole table.
609 * Otherwise we only concern ourselves with the overflowing chunk:
611 * If there are no tombstones in the chunk then we split the chunk in
612 * two, each half full.
614 * If the chunk does contain tombstones, we just make a new copy of
615 * the chunk without the tombstones, which will have room for at least
616 * the one element we have to add.
618 static MonoJitInfoTable*
619 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
621 int num_elements = jit_info_table_num_elements (table);
624 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
625 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
626 //printf ("reallocing table\n");
627 return jit_info_table_realloc (table);
630 /* count the number of non-tombstone elements in the chunk */
632 for (i = 0; i < chunk->num_elements; ++i) {
633 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
637 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
638 //printf ("splitting chunk\n");
639 return jit_info_table_copy_and_split_chunk (table, chunk);
642 //printf ("purifying chunk\n");
643 return jit_info_table_copy_and_purify_chunk (table, chunk);
646 /* We add elements to the table by first making space for them by
647 * shifting the elements at the back to the right, one at a time.
648 * This results in duplicate entries during the process, but during
649 * all the time the table is in a sorted state. Also, when an element
650 * is replaced by another one, the element that replaces it has an end
651 * address that is equal to or lower than that of the replaced
652 * element. That property is necessary to guarantee that when
653 * searching for an element we end up at a position not higher than
654 * the one we're looking for (i.e. we either find the element directly
655 * or we end up to the left of it).
658 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
660 MonoJitInfoTable *table;
662 MonoJitInfoTableChunk *chunk;
666 g_assert (ji->method != NULL);
668 mono_domain_lock (domain);
670 ++mono_stats.jit_info_table_insert_count;
672 table = domain->jit_info_table;
675 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
676 g_assert (chunk_pos < table->num_chunks);
677 chunk = table->chunks [chunk_pos];
679 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
680 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
682 /* Debugging code, should be removed. */
683 //jit_info_table_check (new_table);
685 domain->jit_info_table = new_table;
686 mono_memory_barrier ();
687 domain->num_jit_info_tables++;
688 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free);
694 /* Debugging code, should be removed. */
695 //jit_info_table_check (table);
697 num_elements = chunk->num_elements;
699 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
701 /* First we need to size up the chunk by one, by copying the
702 last item, or inserting the first one, if the table is
704 if (num_elements > 0)
705 chunk->data [num_elements] = chunk->data [num_elements - 1];
707 chunk->data [0] = ji;
708 mono_memory_write_barrier ();
709 chunk->num_elements = ++num_elements;
711 /* Shift the elements up one by one. */
712 for (i = num_elements - 2; i >= pos; --i) {
713 mono_memory_write_barrier ();
714 chunk->data [i + 1] = chunk->data [i];
717 /* Now we have room and can insert the new item. */
718 mono_memory_write_barrier ();
719 chunk->data [pos] = ji;
721 /* Set the high code end address chunk entry. */
722 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
723 + chunk->data [chunk->num_elements - 1]->code_size;
725 /* Debugging code, should be removed. */
726 //jit_info_table_check (table);
728 mono_domain_unlock (domain);
732 mono_jit_info_make_tombstone (MonoJitInfo *ji)
734 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
736 tombstone->code_start = ji->code_start;
737 tombstone->code_size = ji->code_size;
738 tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
744 * LOCKING: domain lock
747 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
749 if (domain->num_jit_info_tables <= 1) {
750 /* Can it actually happen that we only have one table
751 but ji is still hazardous? */
752 mono_thread_hazardous_free_or_queue (ji, g_free);
754 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
759 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
761 MonoJitInfoTable *table;
762 MonoJitInfoTableChunk *chunk;
763 gpointer start = ji->code_start;
766 mono_domain_lock (domain);
767 table = domain->jit_info_table;
769 ++mono_stats.jit_info_table_remove_count;
771 chunk_pos = jit_info_table_index (table, start);
772 g_assert (chunk_pos < table->num_chunks);
774 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
777 chunk = table->chunks [chunk_pos];
779 while (pos < chunk->num_elements) {
780 if (chunk->data [pos] == ji)
783 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
784 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
785 <= (guint8*)ji->code_start + ji->code_size);
792 } while (chunk_pos < table->num_chunks);
795 g_assert (chunk->data [pos] == ji);
797 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
799 /* Debugging code, should be removed. */
800 //jit_info_table_check (table);
802 mono_jit_info_free_or_queue (domain, ji);
804 mono_domain_unlock (domain);
807 static MonoAotModuleInfoTable*
808 mono_aot_module_info_table_new (void)
810 return g_array_new (FALSE, FALSE, sizeof (gpointer));
814 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
816 int left = 0, right = table->len;
818 while (left < right) {
819 int pos = (left + right) / 2;
820 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
821 char *start = ainfo->start;
822 char *end = ainfo->end;
826 else if (addr >= end)
836 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
838 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
841 ainfo->image = image;
842 ainfo->start = start;
845 mono_appdomains_lock ();
848 aot_modules = mono_aot_module_info_table_new ();
850 pos = aot_info_table_index (aot_modules, start);
852 g_array_insert_val (aot_modules, pos, ainfo);
854 mono_appdomains_unlock ();
858 mono_jit_info_find_aot_module (guint8* addr)
860 guint left = 0, right;
865 mono_appdomains_lock ();
867 right = aot_modules->len;
868 while (left < right) {
869 guint pos = (left + right) / 2;
870 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
872 if (addr < (guint8*)ai->start)
874 else if (addr >= (guint8*)ai->end)
877 mono_appdomains_unlock ();
882 mono_appdomains_unlock ();
888 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
890 jit_info_find_in_aot_func = func;
894 mono_jit_info_get_code_start (MonoJitInfo* ji)
896 return ji->code_start;
900 mono_jit_info_get_code_size (MonoJitInfo* ji)
902 return ji->code_size;
906 mono_jit_info_get_method (MonoJitInfo* ji)
912 jit_info_key_extract (gpointer value)
914 MonoJitInfo *info = (MonoJitInfo*)value;
920 jit_info_next_value (gpointer value)
922 MonoJitInfo *info = (MonoJitInfo*)value;
924 return (gpointer*)&info->next_jit_code_hash;
928 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
930 mono_internal_hash_table_init (jit_code_hash,
931 mono_aligned_addr_hash,
932 jit_info_key_extract,
933 jit_info_next_value);
937 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
939 if (ji->has_generic_jit_info)
940 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
946 * mono_jit_info_get_generic_sharing_context:
949 * Returns the jit info's generic sharing context, or NULL if it
952 MonoGenericSharingContext*
953 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
955 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
958 return gi->generic_sharing_context;
964 * mono_jit_info_set_generic_sharing_context:
966 * @gsctx: a generic sharing context
968 * Sets the jit info's generic sharing context. The jit info must
969 * have memory allocated for the context.
972 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
974 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
978 gi->generic_sharing_context = gsctx;
981 MonoTryBlockHoleTableJitInfo*
982 mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
984 if (ji->has_try_block_holes) {
985 char *ptr = (char*)&ji->clauses [ji->num_clauses];
986 if (ji->has_generic_jit_info)
987 ptr += sizeof (MonoGenericJitInfo);
988 return (MonoTryBlockHoleTableJitInfo*)ptr;
994 mono_install_create_domain_hook (MonoCreateDomainFunc func)
996 create_domain_hook = func;
1000 mono_install_free_domain_hook (MonoFreeDomainFunc func)
1002 free_domain_hook = func;
1006 * mono_string_equal:
1007 * @s1: First string to compare
1008 * @s2: Second string to compare
1010 * Returns FALSE if the strings differ.
1013 mono_string_equal (MonoString *s1, MonoString *s2)
1015 int l1 = mono_string_length (s1);
1016 int l2 = mono_string_length (s2);
1023 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
1028 * @s: the string to hash
1030 * Returns the hash for the string.
1033 mono_string_hash (MonoString *s)
1035 const guint16 *p = mono_string_chars (s);
1036 int i, len = mono_string_length (s);
1039 for (i = 0; i < len; i++) {
1040 h = (h << 5) - h + *p;
1048 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1050 int len = GPOINTER_TO_INT (s1 [0]);
1051 if (len != GPOINTER_TO_INT (s2 [0]))
1054 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1058 mono_ptrarray_hash (gpointer *s)
1061 int len = GPOINTER_TO_INT (s [0]);
1064 for (i = 1; i < len; i++)
1065 hash += GPOINTER_TO_UINT (s [i]);
1071 * Allocate an id for domain and set domain->domain_id.
1072 * LOCKING: must be called while holding appdomains_mutex.
1073 * We try to assign low numbers to the domain, so it can be used
1074 * as an index in data tables to lookup domain-specific info
1075 * with minimal memory overhead. We also try not to reuse the
1076 * same id too quickly (to help debugging).
1079 domain_id_alloc (MonoDomain *domain)
1082 if (!appdomains_list) {
1083 appdomain_list_size = 2;
1084 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1086 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1087 if (!appdomains_list [i]) {
1093 for (i = 0; i < appdomain_next; ++i) {
1094 if (!appdomains_list [i]) {
1101 MonoDomain **new_list;
1102 int new_size = appdomain_list_size * 2;
1103 if (new_size >= (1 << 16))
1104 g_assert_not_reached ();
1105 id = appdomain_list_size;
1106 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1107 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1108 mono_gc_free_fixed (appdomains_list);
1109 appdomains_list = new_list;
1110 appdomain_list_size = new_size;
1112 domain->domain_id = id;
1113 appdomains_list [id] = domain;
1115 if (appdomain_next > appdomain_list_size)
1120 static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1121 static gpointer domain_gc_desc = NULL;
1122 static guint32 domain_shadow_serial = 0L;
1125 mono_domain_create (void)
1128 guint32 shadow_serial;
1130 mono_appdomains_lock ();
1131 shadow_serial = domain_shadow_serial++;
1133 if (!domain_gc_desc) {
1134 unsigned int i, bit = 0;
1135 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1136 bit = i / sizeof (gpointer);
1137 domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32);
1139 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1141 mono_appdomains_unlock ();
1143 #ifdef HAVE_BOEHM_GC
1145 * Boehm doesn't like roots inside GC allocated objects, and alloc_fixed returns
1146 * a GC_MALLOC-ed object, contrary to the api docs. This causes random crashes when
1147 * running the corlib test suite.
1148 * To solve this, we pass a NULL descriptor, and don't register roots.
1150 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL);
1152 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1153 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);
1155 domain->shadow_serial = shadow_serial;
1156 domain->domain = NULL;
1157 domain->setup = NULL;
1158 domain->friendly_name = NULL;
1159 domain->search_path = NULL;
1161 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1163 domain->mp = mono_mempool_new ();
1164 domain->code_mp = mono_code_manager_new ();
1165 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1166 domain->domain_assemblies = NULL;
1167 domain->assembly_bindings = NULL;
1168 domain->assembly_bindings_parsed = FALSE;
1169 domain->class_vtable_array = g_ptr_array_new ();
1170 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1171 domain->static_data_array = NULL;
1172 mono_jit_code_hash_init (&domain->jit_code_hash);
1173 domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1174 domain->num_jit_info_tables = 1;
1175 domain->jit_info_table = jit_info_table_new (domain);
1176 domain->jit_info_free_queue = NULL;
1177 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1178 domain->track_resurrection_handles_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1179 domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1181 InitializeCriticalSection (&domain->lock);
1182 InitializeCriticalSection (&domain->assemblies_lock);
1183 InitializeCriticalSection (&domain->jit_code_hash_lock);
1184 InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
1186 domain->method_rgctx_hash = NULL;
1188 mono_appdomains_lock ();
1189 domain_id_alloc (domain);
1190 mono_appdomains_unlock ();
1192 mono_perfcounters->loader_appdomains++;
1193 mono_perfcounters->loader_total_appdomains++;
1195 mono_debug_domain_create (domain);
1197 if (create_domain_hook)
1198 create_domain_hook (domain);
1200 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1206 * mono_init_internal:
1208 * Creates the initial application domain and initializes the mono_defaults
1210 * This function is guaranteed to not run any IL code.
1211 * If exe_filename is not NULL, the method will determine the required runtime
1212 * from the exe configuration file or the version PE field.
1213 * If runtime_version is not NULL, that runtime version will be used.
1214 * Either exe_filename or runtime_version must be provided.
1216 * Returns: the initial domain.
1219 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1221 static MonoDomain *domain = NULL;
1222 MonoAssembly *ass = NULL;
1223 MonoImageOpenStatus status = MONO_IMAGE_OK;
1224 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1228 g_assert_not_reached ();
1231 /* Avoid system error message boxes. */
1232 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1235 mono_perfcounters_init ();
1237 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1238 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1239 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1241 mono_gc_base_init ();
1243 MONO_FAST_TLS_INIT (tls_appdomain);
1244 mono_native_tls_alloc (appdomain_thread_id, NULL);
1246 InitializeCriticalSection (&appdomains_mutex);
1248 mono_metadata_init ();
1249 mono_images_init ();
1250 mono_assemblies_init ();
1251 mono_classes_init ();
1252 mono_loader_init ();
1253 mono_reflection_init ();
1255 /* FIXME: When should we release this memory? */
1256 MONO_GC_REGISTER_ROOT_FIXED (appdomains_list);
1258 domain = mono_domain_create ();
1259 mono_root_domain = domain;
1261 SET_APPDOMAIN (domain);
1263 /* Get a list of runtimes supported by the exe */
1264 if (exe_filename != NULL) {
1266 * This function will load the exe file as a MonoImage. We need to close it, but
1267 * that would mean it would be reloaded later. So instead, we save it to
1268 * exe_image, and close it during shutdown.
1270 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1273 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1275 exe_image = mono_image_open (exe_filename, NULL);
1277 mono_fixup_exe_image (exe_image);
1279 } else if (runtime_version != NULL) {
1280 runtimes [0] = get_runtime_by_version (runtime_version);
1281 runtimes [1] = NULL;
1284 if (runtimes [0] == NULL) {
1285 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1286 runtimes [0] = default_runtime;
1287 runtimes [1] = NULL;
1288 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1289 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1292 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1293 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1294 current_runtime = runtimes [n];
1295 ass = mono_assembly_load_corlib (current_runtime, &status);
1296 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1301 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1303 case MONO_IMAGE_ERROR_ERRNO: {
1304 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1305 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1306 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1307 g_free (corlib_file);
1310 case MONO_IMAGE_IMAGE_INVALID:
1311 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1312 mono_assembly_getrootdir ());
1314 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1315 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1316 mono_assembly_getrootdir ());
1319 /* to suppress compiler warning */
1325 mono_defaults.corlib = mono_assembly_get_image (ass);
1327 mono_defaults.object_class = mono_class_from_name (
1328 mono_defaults.corlib, "System", "Object");
1329 g_assert (mono_defaults.object_class != 0);
1331 mono_defaults.void_class = mono_class_from_name (
1332 mono_defaults.corlib, "System", "Void");
1333 g_assert (mono_defaults.void_class != 0);
1335 mono_defaults.boolean_class = mono_class_from_name (
1336 mono_defaults.corlib, "System", "Boolean");
1337 g_assert (mono_defaults.boolean_class != 0);
1339 mono_defaults.byte_class = mono_class_from_name (
1340 mono_defaults.corlib, "System", "Byte");
1341 g_assert (mono_defaults.byte_class != 0);
1343 mono_defaults.sbyte_class = mono_class_from_name (
1344 mono_defaults.corlib, "System", "SByte");
1345 g_assert (mono_defaults.sbyte_class != 0);
1347 mono_defaults.int16_class = mono_class_from_name (
1348 mono_defaults.corlib, "System", "Int16");
1349 g_assert (mono_defaults.int16_class != 0);
1351 mono_defaults.uint16_class = mono_class_from_name (
1352 mono_defaults.corlib, "System", "UInt16");
1353 g_assert (mono_defaults.uint16_class != 0);
1355 mono_defaults.int32_class = mono_class_from_name (
1356 mono_defaults.corlib, "System", "Int32");
1357 g_assert (mono_defaults.int32_class != 0);
1359 mono_defaults.uint32_class = mono_class_from_name (
1360 mono_defaults.corlib, "System", "UInt32");
1361 g_assert (mono_defaults.uint32_class != 0);
1363 mono_defaults.uint_class = mono_class_from_name (
1364 mono_defaults.corlib, "System", "UIntPtr");
1365 g_assert (mono_defaults.uint_class != 0);
1367 mono_defaults.int_class = mono_class_from_name (
1368 mono_defaults.corlib, "System", "IntPtr");
1369 g_assert (mono_defaults.int_class != 0);
1371 mono_defaults.int64_class = mono_class_from_name (
1372 mono_defaults.corlib, "System", "Int64");
1373 g_assert (mono_defaults.int64_class != 0);
1375 mono_defaults.uint64_class = mono_class_from_name (
1376 mono_defaults.corlib, "System", "UInt64");
1377 g_assert (mono_defaults.uint64_class != 0);
1379 mono_defaults.single_class = mono_class_from_name (
1380 mono_defaults.corlib, "System", "Single");
1381 g_assert (mono_defaults.single_class != 0);
1383 mono_defaults.double_class = mono_class_from_name (
1384 mono_defaults.corlib, "System", "Double");
1385 g_assert (mono_defaults.double_class != 0);
1387 mono_defaults.char_class = mono_class_from_name (
1388 mono_defaults.corlib, "System", "Char");
1389 g_assert (mono_defaults.char_class != 0);
1391 mono_defaults.string_class = mono_class_from_name (
1392 mono_defaults.corlib, "System", "String");
1393 g_assert (mono_defaults.string_class != 0);
1395 mono_defaults.enum_class = mono_class_from_name (
1396 mono_defaults.corlib, "System", "Enum");
1397 g_assert (mono_defaults.enum_class != 0);
1399 mono_defaults.array_class = mono_class_from_name (
1400 mono_defaults.corlib, "System", "Array");
1401 g_assert (mono_defaults.array_class != 0);
1403 mono_defaults.delegate_class = mono_class_from_name (
1404 mono_defaults.corlib, "System", "Delegate");
1405 g_assert (mono_defaults.delegate_class != 0 );
1407 mono_defaults.multicastdelegate_class = mono_class_from_name (
1408 mono_defaults.corlib, "System", "MulticastDelegate");
1409 g_assert (mono_defaults.multicastdelegate_class != 0 );
1411 mono_defaults.asyncresult_class = mono_class_from_name (
1412 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1414 g_assert (mono_defaults.asyncresult_class != 0 );
1416 mono_defaults.manualresetevent_class = mono_class_from_name (
1417 mono_defaults.corlib, "System.Threading", "ManualResetEvent");
1418 g_assert (mono_defaults.manualresetevent_class != 0 );
1420 mono_defaults.typehandle_class = mono_class_from_name (
1421 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1422 g_assert (mono_defaults.typehandle_class != 0);
1424 mono_defaults.methodhandle_class = mono_class_from_name (
1425 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1426 g_assert (mono_defaults.methodhandle_class != 0);
1428 mono_defaults.fieldhandle_class = mono_class_from_name (
1429 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1430 g_assert (mono_defaults.fieldhandle_class != 0);
1432 mono_defaults.systemtype_class = mono_class_from_name (
1433 mono_defaults.corlib, "System", "Type");
1434 g_assert (mono_defaults.systemtype_class != 0);
1436 mono_defaults.monotype_class = mono_class_from_name (
1437 mono_defaults.corlib, "System", "MonoType");
1438 g_assert (mono_defaults.monotype_class != 0);
1440 mono_defaults.exception_class = mono_class_from_name (
1441 mono_defaults.corlib, "System", "Exception");
1442 g_assert (mono_defaults.exception_class != 0);
1444 mono_defaults.threadabortexception_class = mono_class_from_name (
1445 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1446 g_assert (mono_defaults.threadabortexception_class != 0);
1448 mono_defaults.thread_class = mono_class_from_name (
1449 mono_defaults.corlib, "System.Threading", "Thread");
1450 g_assert (mono_defaults.thread_class != 0);
1452 mono_defaults.internal_thread_class = mono_class_from_name (
1453 mono_defaults.corlib, "System.Threading", "InternalThread");
1454 if (!mono_defaults.internal_thread_class) {
1455 /* This can happen with an old mscorlib */
1456 fprintf (stderr, "Corlib too old for this runtime.\n");
1457 fprintf (stderr, "Loaded from: %s\n",
1458 mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown");
1462 mono_defaults.appdomain_class = mono_class_from_name (
1463 mono_defaults.corlib, "System", "AppDomain");
1464 g_assert (mono_defaults.appdomain_class != 0);
1466 mono_defaults.transparent_proxy_class = mono_class_from_name (
1467 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1468 g_assert (mono_defaults.transparent_proxy_class != 0);
1470 mono_defaults.real_proxy_class = mono_class_from_name (
1471 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1472 g_assert (mono_defaults.real_proxy_class != 0);
1474 mono_defaults.mono_method_message_class = mono_class_from_name (
1475 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1476 g_assert (mono_defaults.mono_method_message_class != 0);
1478 mono_defaults.field_info_class = mono_class_from_name (
1479 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1480 g_assert (mono_defaults.field_info_class != 0);
1482 mono_defaults.method_info_class = mono_class_from_name (
1483 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1484 g_assert (mono_defaults.method_info_class != 0);
1486 mono_defaults.stringbuilder_class = mono_class_from_name (
1487 mono_defaults.corlib, "System.Text", "StringBuilder");
1488 g_assert (mono_defaults.stringbuilder_class != 0);
1490 mono_defaults.math_class = mono_class_from_name (
1491 mono_defaults.corlib, "System", "Math");
1492 g_assert (mono_defaults.math_class != 0);
1494 mono_defaults.stack_frame_class = mono_class_from_name (
1495 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1496 g_assert (mono_defaults.stack_frame_class != 0);
1498 mono_defaults.stack_trace_class = mono_class_from_name (
1499 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1500 g_assert (mono_defaults.stack_trace_class != 0);
1502 mono_defaults.marshal_class = mono_class_from_name (
1503 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1504 g_assert (mono_defaults.marshal_class != 0);
1506 mono_defaults.iserializeable_class = mono_class_from_name (
1507 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1508 g_assert (mono_defaults.iserializeable_class != 0);
1510 mono_defaults.serializationinfo_class = mono_class_from_name (
1511 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1512 g_assert (mono_defaults.serializationinfo_class != 0);
1514 mono_defaults.streamingcontext_class = mono_class_from_name (
1515 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1516 g_assert (mono_defaults.streamingcontext_class != 0);
1518 mono_defaults.typed_reference_class = mono_class_from_name (
1519 mono_defaults.corlib, "System", "TypedReference");
1520 g_assert (mono_defaults.typed_reference_class != 0);
1522 mono_defaults.argumenthandle_class = mono_class_from_name (
1523 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1524 g_assert (mono_defaults.argumenthandle_class != 0);
1526 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1527 mono_defaults.corlib, "System", "MarshalByRefObject");
1528 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1530 mono_defaults.monitor_class = mono_class_from_name (
1531 mono_defaults.corlib, "System.Threading", "Monitor");
1532 g_assert (mono_defaults.monitor_class != 0);
1534 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1535 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1536 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1538 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1539 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1541 mono_defaults.executioncontext_class = mono_class_from_name (
1542 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1544 mono_defaults.internals_visible_class = mono_class_from_name (
1545 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1547 mono_defaults.critical_finalizer_object = mono_class_from_name (
1548 mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
1551 * mscorlib needs a little help, only now it can load its friends list (after we have
1552 * loaded the InternalsVisibleToAttribute), load it now
1554 mono_assembly_load_friends (ass);
1556 mono_defaults.safehandle_class = mono_class_from_name (
1557 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1559 mono_defaults.handleref_class = mono_class_from_name (
1560 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1562 mono_defaults.attribute_class = mono_class_from_name (
1563 mono_defaults.corlib, "System", "Attribute");
1565 mono_defaults.customattribute_data_class = mono_class_from_name (
1566 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1568 /* these are initialized lazily when COM features are used */
1569 mono_defaults.variant_class = NULL;
1570 mono_defaults.com_object_class = NULL;
1571 mono_defaults.com_interop_proxy_class = NULL;
1572 mono_defaults.iunknown_class = NULL;
1573 mono_defaults.idispatch_class = NULL;
1576 * Note that mono_defaults.generic_*_class is only non-NULL if we're
1577 * using the 2.0 corlib.
1579 mono_class_init (mono_defaults.array_class);
1580 mono_defaults.generic_nullable_class = mono_class_from_name (
1581 mono_defaults.corlib, "System", "Nullable`1");
1582 mono_defaults.generic_ilist_class = mono_class_from_name (
1583 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1585 domain->friendly_name = g_path_get_basename (filename);
1587 _mono_debug_init_corlib (domain);
1595 * Creates the initial application domain and initializes the mono_defaults
1597 * This function is guaranteed to not run any IL code.
1598 * The runtime is initialized using the default runtime version.
1600 * Returns: the initial domain.
1603 mono_init (const char *domain_name)
1605 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1609 * mono_init_from_assembly:
1610 * @domain_name: name to give to the initial domain
1611 * @filename: filename to load on startup
1613 * Used by the runtime, users should use mono_jit_init instead.
1615 * Creates the initial application domain and initializes the mono_defaults
1617 * This function is guaranteed to not run any IL code.
1618 * The runtime is initialized using the runtime version required by the
1619 * provided executable. The version is determined by looking at the exe
1620 * configuration file and the version PE field)
1622 * Returns: the initial domain.
1625 mono_init_from_assembly (const char *domain_name, const char *filename)
1627 return mono_init_internal (domain_name, filename, NULL);
1631 * mono_init_version:
1633 * Used by the runtime, users should use mono_jit_init instead.
1635 * Creates the initial application domain and initializes the mono_defaults
1638 * This function is guaranteed to not run any IL code.
1639 * The runtime is initialized using the provided rutime version.
1641 * Returns: the initial domain.
1644 mono_init_version (const char *domain_name, const char *version)
1646 return mono_init_internal (domain_name, NULL, version);
1650 * mono_init_com_types:
1652 * Initializes all types needed for COM Interop in mono_defaults structure.
1655 mono_init_com_types (void)
1657 static gboolean initialized = FALSE;
1662 /* FIXME: do I need some threading protection here */
1664 g_assert (mono_defaults.corlib);
1666 mono_defaults.variant_class = mono_class_from_name (
1667 mono_defaults.corlib, "System", "Variant");
1668 g_assert (mono_defaults.variant_class != 0);
1670 mono_defaults.com_object_class = mono_class_from_name (
1671 mono_defaults.corlib, "System", "__ComObject");
1672 g_assert (mono_defaults.com_object_class != 0);
1674 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1675 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1676 g_assert (mono_defaults.com_interop_proxy_class != 0);
1678 mono_defaults.iunknown_class = mono_class_from_name (
1679 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1680 g_assert (mono_defaults.iunknown_class != 0);
1682 mono_defaults.idispatch_class = mono_class_from_name (
1683 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1684 g_assert (mono_defaults.idispatch_class != 0);
1692 * Cleans up all metadata modules.
1697 mono_close_exe_image ();
1699 mono_defaults.corlib = NULL;
1701 mono_config_cleanup ();
1702 mono_loader_cleanup ();
1703 mono_classes_cleanup ();
1704 mono_assemblies_cleanup ();
1705 mono_images_cleanup ();
1706 mono_debug_cleanup ();
1707 mono_metadata_cleanup ();
1709 mono_native_tls_free (appdomain_thread_id);
1710 DeleteCriticalSection (&appdomains_mutex);
1718 mono_close_exe_image (void)
1721 mono_image_close (exe_image);
1725 * mono_get_root_domain:
1727 * The root AppDomain is the initial domain created by the runtime when it is
1728 * initialized. Programs execute on this AppDomain, but can create new ones
1729 * later. Currently there is no unmanaged API to create new AppDomains, this
1730 * must be done from managed code.
1732 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1735 mono_get_root_domain (void)
1737 return mono_root_domain;
1743 * Returns: the current domain, to obtain the root domain use
1744 * mono_get_root_domain().
1749 return GET_APPDOMAIN ();
1753 mono_domain_unset (void)
1755 SET_APPDOMAIN (NULL);
1759 mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception)
1761 MonoInternalThread *thread;
1763 if (mono_domain_get () == domain)
1766 SET_APPDOMAIN (domain);
1767 SET_APPCONTEXT (domain->default_context);
1769 if (migrate_exception) {
1770 thread = mono_thread_internal_current ();
1771 if (!thread->abort_exc)
1774 g_assert (thread->abort_exc->object.vtable->domain != domain);
1775 MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
1776 g_assert (thread->abort_exc->object.vtable->domain == domain);
1781 * mono_domain_set_internal:
1782 * @domain: the new domain
1784 * Sets the current domain to @domain.
1787 mono_domain_set_internal (MonoDomain *domain)
1789 mono_domain_set_internal_with_options (domain, TRUE);
1793 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1799 * Create a copy of the data to avoid calling the user callback
1800 * inside the lock because that could lead to deadlocks.
1801 * We can do this because this function is not perf. critical.
1803 mono_appdomains_lock ();
1804 size = appdomain_list_size;
1805 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1806 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1807 mono_appdomains_unlock ();
1809 for (i = 0; i < size; ++i) {
1811 func (copy [i], user_data);
1814 mono_gc_free_fixed (copy);
1818 * mono_domain_assembly_open:
1819 * @domain: the application domain
1820 * @name: file name of the assembly
1822 * fixme: maybe we should integrate this with mono_assembly_open ??
1825 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1827 MonoDomain *current;
1831 mono_domain_assemblies_lock (domain);
1832 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1834 if (strcmp (name, ass->aname.name) == 0) {
1835 mono_domain_assemblies_unlock (domain);
1839 mono_domain_assemblies_unlock (domain);
1841 if (domain != mono_domain_get ()) {
1842 current = mono_domain_get ();
1844 mono_domain_set (domain, FALSE);
1845 ass = mono_assembly_open (name, NULL);
1846 mono_domain_set (current, FALSE);
1848 ass = mono_assembly_open (name, NULL);
1855 free_slist (gpointer key, gpointer value, gpointer user_data)
1857 g_slist_free (value);
1861 unregister_vtable_reflection_type (MonoVTable *vtable)
1863 MonoObject *type = vtable->type;
1865 if (type->vtable->klass != mono_defaults.monotype_class)
1866 MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type);
1870 mono_domain_free (MonoDomain *domain, gboolean force)
1872 int code_size, code_alloc;
1874 if ((domain == mono_root_domain) && !force) {
1875 g_warning ("cant unload root domain");
1879 if (mono_dont_free_domains)
1882 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1884 mono_debug_domain_unload (domain);
1886 mono_appdomains_lock ();
1887 appdomains_list [domain->domain_id] = NULL;
1888 mono_appdomains_unlock ();
1890 /* must do this early as it accesses fields and types */
1891 if (domain->special_static_fields) {
1892 mono_alloc_special_static_data_free (domain->special_static_fields);
1893 g_hash_table_destroy (domain->special_static_fields);
1894 domain->special_static_fields = NULL;
1898 * We must destroy all these hash tables here because they
1899 * contain references to managed objects belonging to the
1900 * domain. Once we let the GC clear the domain there must be
1901 * no more such references, or we'll crash if a collection
1904 mono_g_hash_table_destroy (domain->ldstr_table);
1905 domain->ldstr_table = NULL;
1907 mono_g_hash_table_destroy (domain->env);
1910 if (domain->tlsrec_list) {
1911 mono_thread_destroy_domain_tls (domain);
1912 domain->tlsrec_list = NULL;
1915 mono_reflection_cleanup_domain (domain);
1917 if (domain->type_hash) {
1918 mono_g_hash_table_destroy (domain->type_hash);
1919 domain->type_hash = NULL;
1921 if (domain->type_init_exception_hash) {
1922 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1923 domain->type_init_exception_hash = NULL;
1926 if (domain->class_vtable_array) {
1928 for (i = 0; i < domain->class_vtable_array->len; ++i)
1929 unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i));
1932 /* This needs to be done before closing assemblies */
1933 mono_gc_clear_domain (domain);
1935 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1936 MonoAssembly *ass = tmp->data;
1937 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s[%p], assembly %s[%p], ref_count=%d\n", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count);
1938 if (!mono_assembly_close_except_image_pools (ass))
1942 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1943 MonoAssembly *ass = tmp->data;
1945 mono_assembly_close_finish (ass);
1947 g_slist_free (domain->domain_assemblies);
1948 domain->domain_assemblies = NULL;
1951 * Send this after the assemblies have been unloaded and the domain is still in a
1954 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
1956 if (free_domain_hook)
1957 free_domain_hook (domain);
1959 /* FIXME: free delegate_hash_table when it's used */
1960 if (domain->search_path) {
1961 g_strfreev (domain->search_path);
1962 domain->search_path = NULL;
1964 domain->create_proxy_for_type_method = NULL;
1965 domain->private_invoke_method = NULL;
1966 domain->default_context = NULL;
1967 domain->out_of_memory_ex = NULL;
1968 domain->null_reference_ex = NULL;
1969 domain->stack_overflow_ex = NULL;
1970 domain->ephemeron_tombstone = NULL;
1971 domain->entry_assembly = NULL;
1973 g_free (domain->friendly_name);
1974 domain->friendly_name = NULL;
1975 g_ptr_array_free (domain->class_vtable_array, TRUE);
1976 domain->class_vtable_array = NULL;
1977 g_hash_table_destroy (domain->proxy_vtable_hash);
1978 domain->proxy_vtable_hash = NULL;
1979 if (domain->static_data_array) {
1980 mono_gc_free_fixed (domain->static_data_array);
1981 domain->static_data_array = NULL;
1983 mono_internal_hash_table_destroy (&domain->jit_code_hash);
1986 * There might still be jit info tables of this domain which
1987 * are not freed. Since the domain cannot be in use anymore,
1988 * this will free them.
1990 mono_thread_hazardous_try_free_all ();
1991 g_assert (domain->num_jit_info_tables == 1);
1992 jit_info_table_free (domain->jit_info_table);
1993 domain->jit_info_table = NULL;
1994 g_assert (!domain->jit_info_free_queue);
1996 /* collect statistics */
1997 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
1998 total_domain_code_alloc += code_alloc;
1999 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
2000 max_domain_code_size = MAX (max_domain_code_size, code_size);
2002 #ifdef DEBUG_DOMAIN_UNLOAD
2003 mono_mempool_invalidate (domain->mp);
2004 mono_code_manager_invalidate (domain->code_mp);
2006 mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
2007 mono_mempool_destroy (domain->mp);
2009 mono_code_manager_destroy (domain->code_mp);
2010 domain->code_mp = NULL;
2013 g_hash_table_destroy (domain->finalizable_objects_hash);
2014 domain->finalizable_objects_hash = NULL;
2015 if (domain->track_resurrection_objects_hash) {
2016 g_hash_table_foreach (domain->track_resurrection_objects_hash, free_slist, NULL);
2017 g_hash_table_destroy (domain->track_resurrection_objects_hash);
2019 if (domain->track_resurrection_handles_hash)
2020 g_hash_table_destroy (domain->track_resurrection_handles_hash);
2021 if (domain->method_rgctx_hash) {
2022 g_hash_table_destroy (domain->method_rgctx_hash);
2023 domain->method_rgctx_hash = NULL;
2025 if (domain->generic_virtual_cases) {
2026 g_hash_table_destroy (domain->generic_virtual_cases);
2027 domain->generic_virtual_cases = NULL;
2029 if (domain->generic_virtual_thunks) {
2030 g_hash_table_destroy (domain->generic_virtual_thunks);
2031 domain->generic_virtual_thunks = NULL;
2033 if (domain->ftnptrs_hash) {
2034 g_hash_table_destroy (domain->ftnptrs_hash);
2035 domain->ftnptrs_hash = NULL;
2038 DeleteCriticalSection (&domain->finalizable_objects_hash_lock);
2039 DeleteCriticalSection (&domain->assemblies_lock);
2040 DeleteCriticalSection (&domain->jit_code_hash_lock);
2041 DeleteCriticalSection (&domain->lock);
2042 domain->setup = NULL;
2044 mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
2046 /* FIXME: anything else required ? */
2048 mono_gc_free_fixed (domain);
2050 mono_perfcounters->loader_appdomains--;
2052 if ((domain == mono_root_domain))
2053 mono_root_domain = NULL;
2057 * mono_domain_get_id:
2060 * Returns: the a domain for a specific domain id.
2063 mono_domain_get_by_id (gint32 domainid)
2065 MonoDomain * domain;
2067 mono_appdomains_lock ();
2068 if (domainid < appdomain_list_size)
2069 domain = appdomains_list [domainid];
2072 mono_appdomains_unlock ();
2078 mono_domain_get_id (MonoDomain *domain)
2080 return domain->domain_id;
2084 * mono_domain_alloc:
2086 * LOCKING: Acquires the domain lock.
2089 mono_domain_alloc (MonoDomain *domain, guint size)
2093 mono_domain_lock (domain);
2094 mono_perfcounters->loader_bytes += size;
2095 res = mono_mempool_alloc (domain->mp, size);
2096 mono_domain_unlock (domain);
2102 * mono_domain_alloc0:
2104 * LOCKING: Acquires the domain lock.
2107 mono_domain_alloc0 (MonoDomain *domain, guint size)
2111 mono_domain_lock (domain);
2112 mono_perfcounters->loader_bytes += size;
2113 res = mono_mempool_alloc0 (domain->mp, size);
2114 mono_domain_unlock (domain);
2120 * mono_domain_code_reserve:
2122 * LOCKING: Acquires the domain lock.
2125 mono_domain_code_reserve (MonoDomain *domain, int size)
2129 mono_domain_lock (domain);
2130 res = mono_code_manager_reserve (domain->code_mp, size);
2131 mono_domain_unlock (domain);
2137 * mono_domain_code_reserve_align:
2139 * LOCKING: Acquires the domain lock.
2142 mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment)
2146 mono_domain_lock (domain);
2147 res = mono_code_manager_reserve_align (domain->code_mp, size, alignment);
2148 mono_domain_unlock (domain);
2154 * mono_domain_code_commit:
2156 * LOCKING: Acquires the domain lock.
2159 mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize)
2161 mono_domain_lock (domain);
2162 mono_code_manager_commit (domain->code_mp, data, size, newsize);
2163 mono_domain_unlock (domain);
2166 #if defined(__native_client_codegen__) && defined(__native_client__)
2168 * Given the temporary buffer (allocated by mono_domain_code_reserve) into which
2169 * we are generating code, return a pointer to the destination in the dynamic
2170 * code segment into which the code will be copied when mono_domain_code_commit
2172 * LOCKING: Acquires the domain lock.
2175 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2178 mono_domain_lock (domain);
2179 dest = nacl_code_manager_get_code_dest (domain->code_mp, data);
2180 mono_domain_unlock (domain);
2185 * Convenience function which calls mono_domain_code_commit to validate and copy
2186 * the code. The caller sets *buf_base and *buf_size to the start and size of
2187 * the buffer (allocated by mono_domain_code_reserve), and *code_end to the byte
2188 * after the last instruction byte. On return, *buf_base will point to the start
2189 * of the copied in the code segment, and *code_end will point after the end of
2193 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2195 guint8 *tmp = nacl_domain_get_code_dest (domain, *buf_base);
2196 mono_domain_code_commit (domain, *buf_base, buf_size, *code_end - *buf_base);
2197 *code_end = tmp + (*code_end - *buf_base);
2203 /* no-op versions of Native Client functions */
2206 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2212 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2219 * mono_domain_code_foreach:
2220 * Iterate over the code thunks of the code manager of @domain.
2222 * The @func callback MUST not take any locks. If it really needs to, it must respect
2223 * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety
2224 * LOCKING: Acquires the domain lock.
2228 mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data)
2230 mono_domain_lock (domain);
2231 mono_code_manager_foreach (domain->code_mp, func, user_data);
2232 mono_domain_unlock (domain);
2237 mono_context_set (MonoAppContext * new_context)
2239 SET_APPCONTEXT (new_context);
2243 mono_context_get (void)
2245 return GET_APPCONTEXT ();
2248 /* LOCKING: the caller holds the lock for this domain */
2250 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
2252 /* The first entry in the array is the index of the next free slot
2253 * and the total size of the array
2256 if (domain->static_data_array) {
2257 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
2258 next = GPOINTER_TO_INT (domain->static_data_array [0]);
2260 /* 'data' is allocated by alloc_fixed */
2261 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2));
2262 mono_gc_memmove (new_array, domain->static_data_array, sizeof (gpointer) * size);
2264 new_array [1] = GINT_TO_POINTER (size);
2265 mono_gc_free_fixed (domain->static_data_array);
2266 domain->static_data_array = new_array;
2270 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, MONO_GC_ROOT_DESCR_FOR_FIXED (size));
2272 new_array [0] = GINT_TO_POINTER (next);
2273 new_array [1] = GINT_TO_POINTER (size);
2274 domain->static_data_array = new_array;
2276 domain->static_data_array [next++] = data;
2277 domain->static_data_array [0] = GINT_TO_POINTER (next);
2281 mono_get_corlib (void)
2283 return mono_defaults.corlib;
2287 mono_get_object_class (void)
2289 return mono_defaults.object_class;
2293 mono_get_byte_class (void)
2295 return mono_defaults.byte_class;
2299 mono_get_void_class (void)
2301 return mono_defaults.void_class;
2305 mono_get_boolean_class (void)
2307 return mono_defaults.boolean_class;
2311 mono_get_sbyte_class (void)
2313 return mono_defaults.sbyte_class;
2317 mono_get_int16_class (void)
2319 return mono_defaults.int16_class;
2323 mono_get_uint16_class (void)
2325 return mono_defaults.uint16_class;
2329 mono_get_int32_class (void)
2331 return mono_defaults.int32_class;
2335 mono_get_uint32_class (void)
2337 return mono_defaults.uint32_class;
2341 mono_get_intptr_class (void)
2343 return mono_defaults.int_class;
2347 mono_get_uintptr_class (void)
2349 return mono_defaults.uint_class;
2353 mono_get_int64_class (void)
2355 return mono_defaults.int64_class;
2359 mono_get_uint64_class (void)
2361 return mono_defaults.uint64_class;
2365 mono_get_single_class (void)
2367 return mono_defaults.single_class;
2371 mono_get_double_class (void)
2373 return mono_defaults.double_class;
2377 mono_get_char_class (void)
2379 return mono_defaults.char_class;
2383 mono_get_string_class (void)
2385 return mono_defaults.string_class;
2389 mono_get_enum_class (void)
2391 return mono_defaults.enum_class;
2395 mono_get_array_class (void)
2397 return mono_defaults.array_class;
2401 mono_get_thread_class (void)
2403 return mono_defaults.thread_class;
2407 mono_get_exception_class (void)
2409 return mono_defaults.exception_class;
2413 static char* get_attribute_value (const gchar **attribute_names,
2414 const gchar **attribute_values,
2415 const char *att_name)
2418 for (n=0; attribute_names[n] != NULL; n++) {
2419 if (strcmp (attribute_names[n], att_name) == 0)
2420 return g_strdup (attribute_values[n]);
2425 static void start_element (GMarkupParseContext *context,
2426 const gchar *element_name,
2427 const gchar **attribute_names,
2428 const gchar **attribute_values,
2432 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2434 if (strcmp (element_name, "configuration") == 0) {
2435 app_config->configuration_count++;
2438 if (strcmp (element_name, "startup") == 0) {
2439 app_config->startup_count++;
2443 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2446 if (strcmp (element_name, "requiredRuntime") == 0) {
2447 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2448 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2449 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2450 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2454 static void end_element (GMarkupParseContext *context,
2455 const gchar *element_name,
2459 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2461 if (strcmp (element_name, "configuration") == 0) {
2462 app_config->configuration_count--;
2463 } else if (strcmp (element_name, "startup") == 0) {
2464 app_config->startup_count--;
2468 static const GMarkupParser
2477 static AppConfigInfo *
2478 app_config_parse (const char *exe_filename)
2480 AppConfigInfo *app_config;
2481 GMarkupParseContext *context;
2484 const char *bundled_config;
2485 char *config_filename;
2487 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2489 if (bundled_config) {
2490 text = g_strdup (bundled_config);
2491 len = strlen (text);
2493 config_filename = g_strconcat (exe_filename, ".config", NULL);
2495 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2496 g_free (config_filename);
2499 g_free (config_filename);
2502 app_config = g_new0 (AppConfigInfo, 1);
2504 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2505 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2506 g_markup_parse_context_end_parse (context, NULL);
2508 g_markup_parse_context_free (context);
2514 app_config_free (AppConfigInfo* app_config)
2517 GSList *list = app_config->supported_runtimes;
2518 while (list != NULL) {
2519 rt = (char*)list->data;
2521 list = g_slist_next (list);
2523 g_slist_free (app_config->supported_runtimes);
2524 g_free (app_config->required_runtime);
2525 g_free (app_config);
2529 static const MonoRuntimeInfo*
2530 get_runtime_by_version (const char *version)
2533 int max = G_N_ELEMENTS (supported_runtimes);
2534 gboolean do_partial_match;
2540 vlen = strlen (version);
2541 if (vlen >= 4 && version [1] - '0' >= 4)
2542 do_partial_match = TRUE;
2544 do_partial_match = FALSE;
2546 for (n=0; n<max; n++) {
2547 if (do_partial_match && strncmp (version, supported_runtimes[n].runtime_version, 4) == 0)
2548 return &supported_runtimes[n];
2549 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2550 return &supported_runtimes[n];
2556 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2558 AppConfigInfo* app_config;
2560 const MonoRuntimeInfo* runtime = NULL;
2561 MonoImage *image = NULL;
2563 app_config = app_config_parse (exe_file);
2565 if (app_config != NULL) {
2566 /* Check supportedRuntime elements, if none is supported, fail.
2567 * If there are no such elements, look for a requiredRuntime element.
2569 if (app_config->supported_runtimes != NULL) {
2571 GSList *list = app_config->supported_runtimes;
2572 while (list != NULL) {
2573 version = (char*) list->data;
2574 runtime = get_runtime_by_version (version);
2575 if (runtime != NULL)
2576 runtimes [n++] = runtime;
2577 list = g_slist_next (list);
2579 runtimes [n] = NULL;
2580 app_config_free (app_config);
2584 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2585 if (app_config->required_runtime != NULL) {
2586 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2587 runtimes [1] = NULL;
2588 app_config_free (app_config);
2591 app_config_free (app_config);
2594 /* Look for a runtime with the exact version */
2595 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2598 image = mono_image_open (exe_file, NULL);
2600 if (image == NULL) {
2601 /* The image is wrong or the file was not found. In this case return
2602 * a default runtime and leave to the initialization method the work of
2603 * reporting the error.
2605 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2606 runtimes [1] = NULL;
2612 runtimes [0] = get_runtime_by_version (image->version);
2613 runtimes [1] = NULL;
2618 * mono_get_runtime_info:
2620 * Returns: the version of the current runtime instance.
2622 const MonoRuntimeInfo*
2623 mono_get_runtime_info (void)
2625 return current_runtime;
2629 mono_debugger_check_runtime_version (const char *filename)
2631 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2632 const MonoRuntimeInfo *rinfo;
2635 get_runtimes_from_exe (filename, &image, runtimes);
2636 rinfo = runtimes [0];
2639 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2641 if (rinfo != current_runtime)
2642 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2643 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2644 filename, rinfo->runtime_version);
2650 * mono_framework_version:
2652 * Return the major version of the framework curently executing.
2655 mono_framework_version (void)
2657 return current_runtime->framework_version [0] - '0';