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/metadata/object.h>
25 #include <mono/metadata/object-internals.h>
26 #include <mono/metadata/domain-internals.h>
27 #include <mono/metadata/class-internals.h>
28 #include <mono/metadata/assembly.h>
29 #include <mono/metadata/exception.h>
30 #include <mono/metadata/metadata-internals.h>
31 #include <mono/metadata/gc-internal.h>
32 #include <mono/metadata/appdomain.h>
33 #include <mono/metadata/mono-debug-debugger.h>
34 #include <mono/metadata/mono-config.h>
35 #include <mono/metadata/threads-types.h>
36 #include <metadata/threads.h>
37 #include <metadata/profiler-private.h>
38 #include <mono/metadata/coree.h>
40 /* #define DEBUG_DOMAIN_UNLOAD */
42 /* we need to use both the Tls* functions and __thread because
43 * some archs may generate faster jit code with one meachanism
44 * or the other (we used to do it because tls slots were GC-tracked,
45 * but we can't depend on this).
47 static guint32 appdomain_thread_id = -1;
50 * Avoid calling TlsSetValue () if possible, since in the io-layer, it acquires
51 * a global lock (!) so it is a contention point.
53 #if (defined(__i386__) || defined(__x86_64__)) && !defined(HOST_WIN32)
54 #define NO_TLS_SET_VALUE
57 #ifdef MONO_HAVE_FAST_TLS
59 MONO_FAST_TLS_DECLARE(tls_appdomain);
61 #define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain))
63 #ifdef NO_TLS_SET_VALUE
64 #define SET_APPDOMAIN(x) do { \
65 MONO_FAST_TLS_SET (tls_appdomain,x); \
68 #define SET_APPDOMAIN(x) do { \
69 MONO_FAST_TLS_SET (tls_appdomain,x); \
70 TlsSetValue (appdomain_thread_id, x); \
74 #else /* !MONO_HAVE_FAST_TLS */
76 #define GET_APPDOMAIN() ((MonoDomain *)TlsGetValue (appdomain_thread_id))
77 #define SET_APPDOMAIN(x) TlsSetValue (appdomain_thread_id, x);
81 #define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext)
82 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x))
84 static guint16 appdomain_list_size = 0;
85 static guint16 appdomain_next = 0;
86 static MonoDomain **appdomains_list = NULL;
87 static MonoImage *exe_image;
89 gboolean mono_dont_free_domains;
91 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
92 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
93 static CRITICAL_SECTION appdomains_mutex;
95 static MonoDomain *mono_root_domain = NULL;
98 static int max_domain_code_size = 0;
99 static int max_domain_code_alloc = 0;
100 static int total_domain_code_alloc = 0;
102 /* AppConfigInfo: Information about runtime versions supported by an
106 GSList *supported_runtimes;
107 char *required_runtime;
108 int configuration_count;
113 * AotModuleInfo: Contains information about AOT modules.
120 static const MonoRuntimeInfo *current_runtime = NULL;
122 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
125 * Contains information about AOT loaded code.
127 static MonoAotModuleInfoTable *aot_modules = NULL;
129 /* This is the list of runtime versions supported by this JIT.
131 static const MonoRuntimeInfo supported_runtimes[] = {
132 {"v2.0.50215","2.0", { {2,0,0,0}, {8,0,0,0}, { 3, 5, 0, 0 } } },
133 {"v2.0.50727","2.0", { {2,0,0,0}, {8,0,0,0}, { 3, 5, 0, 0 } } },
134 {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } },
135 {"v4.0.30128","4.0", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } },
136 {"v4.0.30319","4.0", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } },
137 {"moonlight", "2.1", { {2,0,5,0}, {9,0,0,0}, { 3, 5, 0, 0 } } },
141 /* The stable runtime version */
142 #define DEFAULT_RUNTIME_VERSION "v2.0.50727"
144 /* Callbacks installed by the JIT */
145 static MonoCreateDomainFunc create_domain_hook;
146 static MonoFreeDomainFunc free_domain_hook;
148 /* This is intentionally not in the header file, so people don't misuse it. */
149 extern void _mono_debug_init_corlib (MonoDomain *domain);
152 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
154 static const MonoRuntimeInfo*
155 get_runtime_by_version (const char *version);
158 mono_jit_info_find_aot_module (guint8* addr);
161 mono_domain_get_tls_key (void)
163 return appdomain_thread_id;
167 mono_domain_get_tls_offset (void)
170 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
171 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
176 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
177 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
178 #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)
180 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
181 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
183 #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
184 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
186 #define JIT_INFO_TABLE_HAZARD_INDEX 0
187 #define JIT_INFO_HAZARD_INDEX 1
190 jit_info_table_num_elements (MonoJitInfoTable *table)
193 int num_elements = 0;
195 for (i = 0; i < table->num_chunks; ++i) {
196 MonoJitInfoTableChunk *chunk = table->chunks [i];
197 int chunk_num_elements = chunk->num_elements;
200 for (j = 0; j < chunk_num_elements; ++j) {
201 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
209 static MonoJitInfoTableChunk*
210 jit_info_table_new_chunk (void)
212 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
218 static MonoJitInfoTable *
219 jit_info_table_new (MonoDomain *domain)
221 MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
223 table->domain = domain;
224 table->num_chunks = 1;
225 table->chunks [0] = jit_info_table_new_chunk ();
231 jit_info_table_free (MonoJitInfoTable *table)
234 int num_chunks = table->num_chunks;
235 MonoDomain *domain = table->domain;
237 mono_domain_lock (domain);
239 table->domain->num_jit_info_tables--;
240 if (table->domain->num_jit_info_tables <= 1) {
243 for (list = table->domain->jit_info_free_queue; list; list = list->next)
246 g_slist_free (table->domain->jit_info_free_queue);
247 table->domain->jit_info_free_queue = NULL;
250 /* At this point we assume that there are no other threads
251 still accessing the table, so we don't have to worry about
252 hazardous pointers. */
254 for (i = 0; i < num_chunks; ++i) {
255 MonoJitInfoTableChunk *chunk = table->chunks [i];
259 if (--chunk->refcount > 0)
262 num_elements = chunk->num_elements;
263 for (j = 0; j < num_elements; ++j) {
264 MonoJitInfo *ji = chunk->data [j];
266 if (IS_JIT_INFO_TOMBSTONE (ji))
273 mono_domain_unlock (domain);
278 /* The jit_info_table is sorted in ascending order by the end
279 * addresses of the compiled methods. The reason why we have to do
280 * this is that once we introduce tombstones, it becomes possible for
281 * code ranges to overlap, and if we sort by code start and insert at
282 * the back of the table, we cannot guarantee that we won't overlook
285 * There are actually two possible ways to do the sorting and
286 * inserting which work with our lock-free mechanism:
288 * 1. Sort by start address and insert at the front. When looking for
289 * an entry, find the last one with a start address lower than the one
290 * you're looking for, then work your way to the front of the table.
292 * 2. Sort by end address and insert at the back. When looking for an
293 * entry, find the first one with an end address higher than the one
294 * you're looking for, then work your way to the end of the table.
296 * We chose the latter out of convenience.
299 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
301 int left = 0, right = table->num_chunks;
303 g_assert (left < right);
306 int pos = (left + right) / 2;
307 MonoJitInfoTableChunk *chunk = table->chunks [pos];
309 if (addr < chunk->last_code_end)
313 } while (left < right);
314 g_assert (left == right);
316 if (left >= table->num_chunks)
317 return table->num_chunks - 1;
322 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
324 int left = 0, right = chunk->num_elements;
326 while (left < right) {
327 int pos = (left + right) / 2;
328 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
329 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
336 g_assert (left == right);
342 mono_jit_info_table_find (MonoDomain *domain, char *addr)
344 MonoJitInfoTable *table;
347 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
350 ++mono_stats.jit_info_table_lookup_count;
352 /* First we have to get the domain's jit_info_table. This is
353 complicated by the fact that a writer might substitute a
354 new table and free the old one. What the writer guarantees
355 us is that it looks at the hazard pointers after it has
356 changed the jit_info_table pointer. So, if we guard the
357 table by a hazard pointer and make sure that the pointer is
358 still there after we've made it hazardous, we don't have to
359 worry about the writer freeing the table. */
360 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
362 chunk_pos = jit_info_table_index (table, (gint8*)addr);
363 g_assert (chunk_pos < table->num_chunks);
365 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
367 /* We now have a position that's very close to that of the
368 first element whose end address is higher than the one
369 we're looking for. If we don't have the exact position,
370 then we have a position below that one, so we'll just
371 search upward until we find our element. */
373 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
375 while (pos < chunk->num_elements) {
376 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
380 if (IS_JIT_INFO_TOMBSTONE (ji)) {
381 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
384 if ((gint8*)addr >= (gint8*)ji->code_start
385 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
386 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
387 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
391 /* If we find a non-tombstone element which is already
392 beyond what we're looking for, we have to end the
394 if ((gint8*)addr < (gint8*)ji->code_start)
400 } while (chunk_pos < table->num_chunks);
406 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
407 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
411 /* Maybe its an AOT module */
412 image = mono_jit_info_find_aot_module ((guint8*)addr);
414 ji = jit_info_find_in_aot_func (domain, image, addr);
419 static G_GNUC_UNUSED void
420 jit_info_table_check (MonoJitInfoTable *table)
424 for (i = 0; i < table->num_chunks; ++i) {
425 MonoJitInfoTableChunk *chunk = table->chunks [i];
428 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
429 if (chunk->refcount > 10)
430 printf("warning: chunk refcount is %d\n", chunk->refcount);
431 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
433 for (j = 0; j < chunk->num_elements; ++j) {
434 MonoJitInfo *this = chunk->data [j];
437 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
439 if (j < chunk->num_elements - 1)
440 next = chunk->data [j + 1];
441 else if (i < table->num_chunks - 1) {
444 for (k = i + 1; k < table->num_chunks; ++k)
445 if (table->chunks [k]->num_elements > 0)
448 if (k >= table->num_chunks)
451 g_assert (table->chunks [k]->num_elements > 0);
452 next = table->chunks [k]->data [0];
456 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
461 static MonoJitInfoTable*
462 jit_info_table_realloc (MonoJitInfoTable *old)
465 int num_elements = jit_info_table_num_elements (old);
468 int new_chunk, new_element;
469 MonoJitInfoTable *new;
471 /* number of needed places for elements needed */
472 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
473 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
475 new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
476 new->domain = old->domain;
477 new->num_chunks = num_chunks;
479 for (i = 0; i < num_chunks; ++i)
480 new->chunks [i] = jit_info_table_new_chunk ();
484 for (i = 0; i < old->num_chunks; ++i) {
485 MonoJitInfoTableChunk *chunk = old->chunks [i];
486 int chunk_num_elements = chunk->num_elements;
489 for (j = 0; j < chunk_num_elements; ++j) {
490 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
491 g_assert (new_chunk < num_chunks);
492 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
493 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
494 new->chunks [new_chunk]->num_elements = new_element;
502 if (new_chunk < num_chunks) {
503 g_assert (new_chunk == num_chunks - 1);
504 new->chunks [new_chunk]->num_elements = new_element;
505 g_assert (new->chunks [new_chunk]->num_elements > 0);
508 for (i = 0; i < num_chunks; ++i) {
509 MonoJitInfoTableChunk *chunk = new->chunks [i];
510 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
512 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
519 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
521 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
522 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
524 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
526 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
527 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
529 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
530 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
532 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
533 + new1->data [new1->num_elements - 1]->code_size;
534 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
535 + new2->data [new2->num_elements - 1]->code_size;
541 static MonoJitInfoTable*
542 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
544 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
545 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
548 new_table->domain = table->domain;
549 new_table->num_chunks = table->num_chunks + 1;
552 for (i = 0; i < table->num_chunks; ++i) {
553 if (table->chunks [i] == chunk) {
554 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
557 new_table->chunks [j] = table->chunks [i];
558 ++new_table->chunks [j]->refcount;
563 g_assert (j == new_table->num_chunks);
568 static MonoJitInfoTableChunk*
569 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
571 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
575 for (i = 0; i < old->num_elements; ++i) {
576 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
577 new->data [j++] = old->data [i];
580 new->num_elements = j;
581 if (new->num_elements > 0)
582 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
584 new->last_code_end = old->last_code_end;
589 static MonoJitInfoTable*
590 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
592 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
593 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
596 new_table->domain = table->domain;
597 new_table->num_chunks = table->num_chunks;
600 for (i = 0; i < table->num_chunks; ++i) {
601 if (table->chunks [i] == chunk)
602 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
604 new_table->chunks [j] = table->chunks [i];
605 ++new_table->chunks [j]->refcount;
610 g_assert (j == new_table->num_chunks);
615 /* As we add an element to the table the case can arise that the chunk
616 * to which we need to add is already full. In that case we have to
617 * allocate a new table and do something about that chunk. We have
618 * several strategies:
620 * If the number of elements in the table is below the low watermark
621 * or above the high watermark, we reallocate the whole table.
622 * Otherwise we only concern ourselves with the overflowing chunk:
624 * If there are no tombstones in the chunk then we split the chunk in
625 * two, each half full.
627 * If the chunk does contain tombstones, we just make a new copy of
628 * the chunk without the tombstones, which will have room for at least
629 * the one element we have to add.
631 static MonoJitInfoTable*
632 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
634 int num_elements = jit_info_table_num_elements (table);
637 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
638 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
639 //printf ("reallocing table\n");
640 return jit_info_table_realloc (table);
643 /* count the number of non-tombstone elements in the chunk */
645 for (i = 0; i < chunk->num_elements; ++i) {
646 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
650 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
651 //printf ("splitting chunk\n");
652 return jit_info_table_copy_and_split_chunk (table, chunk);
655 //printf ("purifying chunk\n");
656 return jit_info_table_copy_and_purify_chunk (table, chunk);
659 /* We add elements to the table by first making space for them by
660 * shifting the elements at the back to the right, one at a time.
661 * This results in duplicate entries during the process, but during
662 * all the time the table is in a sorted state. Also, when an element
663 * is replaced by another one, the element that replaces it has an end
664 * address that is equal to or lower than that of the replaced
665 * element. That property is necessary to guarantee that when
666 * searching for an element we end up at a position not higher than
667 * the one we're looking for (i.e. we either find the element directly
668 * or we end up to the left of it).
671 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
673 MonoJitInfoTable *table;
675 MonoJitInfoTableChunk *chunk;
679 g_assert (ji->method != NULL);
681 mono_domain_lock (domain);
683 ++mono_stats.jit_info_table_insert_count;
685 table = domain->jit_info_table;
688 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
689 g_assert (chunk_pos < table->num_chunks);
690 chunk = table->chunks [chunk_pos];
692 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
693 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
695 /* Debugging code, should be removed. */
696 //jit_info_table_check (new_table);
698 domain->jit_info_table = new_table;
699 mono_memory_barrier ();
700 domain->num_jit_info_tables++;
701 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free);
707 /* Debugging code, should be removed. */
708 //jit_info_table_check (table);
710 num_elements = chunk->num_elements;
712 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
714 /* First we need to size up the chunk by one, by copying the
715 last item, or inserting the first one, if the table is
717 if (num_elements > 0)
718 chunk->data [num_elements] = chunk->data [num_elements - 1];
720 chunk->data [0] = ji;
721 mono_memory_write_barrier ();
722 chunk->num_elements = ++num_elements;
724 /* Shift the elements up one by one. */
725 for (i = num_elements - 2; i >= pos; --i) {
726 mono_memory_write_barrier ();
727 chunk->data [i + 1] = chunk->data [i];
730 /* Now we have room and can insert the new item. */
731 mono_memory_write_barrier ();
732 chunk->data [pos] = ji;
734 /* Set the high code end address chunk entry. */
735 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
736 + chunk->data [chunk->num_elements - 1]->code_size;
738 /* Debugging code, should be removed. */
739 //jit_info_table_check (table);
741 mono_domain_unlock (domain);
745 mono_jit_info_make_tombstone (MonoJitInfo *ji)
747 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
749 tombstone->code_start = ji->code_start;
750 tombstone->code_size = ji->code_size;
751 tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
757 * LOCKING: domain lock
760 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
762 if (domain->num_jit_info_tables <= 1) {
763 /* Can it actually happen that we only have one table
764 but ji is still hazardous? */
765 mono_thread_hazardous_free_or_queue (ji, g_free);
767 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
772 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
774 MonoJitInfoTable *table;
775 MonoJitInfoTableChunk *chunk;
776 gpointer start = ji->code_start;
779 mono_domain_lock (domain);
780 table = domain->jit_info_table;
782 ++mono_stats.jit_info_table_remove_count;
784 chunk_pos = jit_info_table_index (table, start);
785 g_assert (chunk_pos < table->num_chunks);
787 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
790 chunk = table->chunks [chunk_pos];
792 while (pos < chunk->num_elements) {
793 if (chunk->data [pos] == ji)
796 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
797 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
798 <= (guint8*)ji->code_start + ji->code_size);
805 } while (chunk_pos < table->num_chunks);
808 g_assert (chunk->data [pos] == ji);
810 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
812 /* Debugging code, should be removed. */
813 //jit_info_table_check (table);
815 mono_jit_info_free_or_queue (domain, ji);
817 mono_domain_unlock (domain);
820 static MonoAotModuleInfoTable*
821 mono_aot_module_info_table_new (void)
823 return g_array_new (FALSE, FALSE, sizeof (gpointer));
827 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
829 int left = 0, right = table->len;
831 while (left < right) {
832 int pos = (left + right) / 2;
833 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
834 char *start = ainfo->start;
835 char *end = ainfo->end;
839 else if (addr >= end)
849 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
851 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
854 ainfo->image = image;
855 ainfo->start = start;
858 mono_appdomains_lock ();
861 aot_modules = mono_aot_module_info_table_new ();
863 pos = aot_info_table_index (aot_modules, start);
865 g_array_insert_val (aot_modules, pos, ainfo);
867 mono_appdomains_unlock ();
871 mono_jit_info_find_aot_module (guint8* addr)
873 guint left = 0, right;
878 mono_appdomains_lock ();
880 right = aot_modules->len;
881 while (left < right) {
882 guint pos = (left + right) / 2;
883 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
885 if (addr < (guint8*)ai->start)
887 else if (addr >= (guint8*)ai->end)
890 mono_appdomains_unlock ();
895 mono_appdomains_unlock ();
901 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
903 jit_info_find_in_aot_func = func;
907 mono_jit_info_get_code_start (MonoJitInfo* ji)
909 return ji->code_start;
913 mono_jit_info_get_code_size (MonoJitInfo* ji)
915 return ji->code_size;
919 mono_jit_info_get_method (MonoJitInfo* ji)
925 jit_info_key_extract (gpointer value)
927 MonoJitInfo *info = (MonoJitInfo*)value;
933 jit_info_next_value (gpointer value)
935 MonoJitInfo *info = (MonoJitInfo*)value;
937 return (gpointer*)&info->next_jit_code_hash;
941 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
943 mono_internal_hash_table_init (jit_code_hash,
944 mono_aligned_addr_hash,
945 jit_info_key_extract,
946 jit_info_next_value);
950 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
952 if (ji->has_generic_jit_info)
953 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
959 * mono_jit_info_get_generic_sharing_context:
962 * Returns the jit info's generic sharing context, or NULL if it
965 MonoGenericSharingContext*
966 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
968 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
971 return gi->generic_sharing_context;
977 * mono_jit_info_set_generic_sharing_context:
979 * @gsctx: a generic sharing context
981 * Sets the jit info's generic sharing context. The jit info must
982 * have memory allocated for the context.
985 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
987 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
991 gi->generic_sharing_context = gsctx;
994 MonoTryBlockHoleTableJitInfo*
995 mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
997 if (ji->has_try_block_holes) {
998 char *ptr = (char*)&ji->clauses [ji->num_clauses];
999 if (ji->has_generic_jit_info)
1000 ptr += sizeof (MonoGenericJitInfo);
1001 return (MonoTryBlockHoleTableJitInfo*)ptr;
1007 mono_install_create_domain_hook (MonoCreateDomainFunc func)
1009 create_domain_hook = func;
1013 mono_install_free_domain_hook (MonoFreeDomainFunc func)
1015 free_domain_hook = func;
1019 * mono_string_equal:
1020 * @s1: First string to compare
1021 * @s2: Second string to compare
1023 * Returns FALSE if the strings differ.
1026 mono_string_equal (MonoString *s1, MonoString *s2)
1028 int l1 = mono_string_length (s1);
1029 int l2 = mono_string_length (s2);
1036 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
1041 * @s: the string to hash
1043 * Returns the hash for the string.
1046 mono_string_hash (MonoString *s)
1048 const guint16 *p = mono_string_chars (s);
1049 int i, len = mono_string_length (s);
1052 for (i = 0; i < len; i++) {
1053 h = (h << 5) - h + *p;
1061 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1063 int len = GPOINTER_TO_INT (s1 [0]);
1064 if (len != GPOINTER_TO_INT (s2 [0]))
1067 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1071 mono_ptrarray_hash (gpointer *s)
1074 int len = GPOINTER_TO_INT (s [0]);
1077 for (i = 1; i < len; i++)
1078 hash += GPOINTER_TO_UINT (s [i]);
1084 * Allocate an id for domain and set domain->domain_id.
1085 * LOCKING: must be called while holding appdomains_mutex.
1086 * We try to assign low numbers to the domain, so it can be used
1087 * as an index in data tables to lookup domain-specific info
1088 * with minimal memory overhead. We also try not to reuse the
1089 * same id too quickly (to help debugging).
1092 domain_id_alloc (MonoDomain *domain)
1095 if (!appdomains_list) {
1096 appdomain_list_size = 2;
1097 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1099 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1100 if (!appdomains_list [i]) {
1106 for (i = 0; i < appdomain_next; ++i) {
1107 if (!appdomains_list [i]) {
1114 MonoDomain **new_list;
1115 int new_size = appdomain_list_size * 2;
1116 if (new_size >= (1 << 16))
1117 g_assert_not_reached ();
1118 id = appdomain_list_size;
1119 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1120 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1121 mono_gc_free_fixed (appdomains_list);
1122 appdomains_list = new_list;
1123 appdomain_list_size = new_size;
1125 domain->domain_id = id;
1126 appdomains_list [id] = domain;
1128 if (appdomain_next > appdomain_list_size)
1133 static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1134 static gpointer domain_gc_desc = NULL;
1135 static guint32 domain_shadow_serial = 0L;
1138 mono_domain_create (void)
1141 guint32 shadow_serial;
1143 mono_appdomains_lock ();
1144 shadow_serial = domain_shadow_serial++;
1146 if (!domain_gc_desc) {
1147 unsigned int i, bit = 0;
1148 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1149 bit = i / sizeof (gpointer);
1150 domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32);
1152 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1154 mono_appdomains_unlock ();
1156 #ifdef HAVE_BOEHM_GC
1158 * Boehm doesn't like roots inside GC allocated objects, and alloc_fixed returns
1159 * a GC_MALLOC-ed object, contrary to the api docs. This causes random crashes when
1160 * running the corlib test suite.
1161 * To solve this, we pass a NULL descriptor, and don't register roots.
1163 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL);
1165 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1166 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);
1168 domain->shadow_serial = shadow_serial;
1169 domain->domain = NULL;
1170 domain->setup = NULL;
1171 domain->friendly_name = NULL;
1172 domain->search_path = NULL;
1174 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1176 domain->mp = mono_mempool_new ();
1177 domain->code_mp = mono_code_manager_new ();
1178 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1179 domain->domain_assemblies = NULL;
1180 domain->assembly_bindings = NULL;
1181 domain->assembly_bindings_parsed = FALSE;
1182 domain->class_vtable_array = g_ptr_array_new ();
1183 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1184 domain->static_data_array = NULL;
1185 mono_jit_code_hash_init (&domain->jit_code_hash);
1186 domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1187 domain->num_jit_info_tables = 1;
1188 domain->jit_info_table = jit_info_table_new (domain);
1189 domain->jit_info_free_queue = NULL;
1190 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1191 domain->track_resurrection_handles_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1192 domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1194 InitializeCriticalSection (&domain->lock);
1195 InitializeCriticalSection (&domain->assemblies_lock);
1196 InitializeCriticalSection (&domain->jit_code_hash_lock);
1197 InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
1199 domain->method_rgctx_hash = NULL;
1201 mono_appdomains_lock ();
1202 domain_id_alloc (domain);
1203 mono_appdomains_unlock ();
1205 mono_perfcounters->loader_appdomains++;
1206 mono_perfcounters->loader_total_appdomains++;
1208 mono_debug_domain_create (domain);
1210 if (create_domain_hook)
1211 create_domain_hook (domain);
1213 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1219 * mono_init_internal:
1221 * Creates the initial application domain and initializes the mono_defaults
1223 * This function is guaranteed to not run any IL code.
1224 * If exe_filename is not NULL, the method will determine the required runtime
1225 * from the exe configuration file or the version PE field.
1226 * If runtime_version is not NULL, that runtime version will be used.
1227 * Either exe_filename or runtime_version must be provided.
1229 * Returns: the initial domain.
1232 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1234 static MonoDomain *domain = NULL;
1235 MonoAssembly *ass = NULL;
1236 MonoImageOpenStatus status = MONO_IMAGE_OK;
1237 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1241 g_assert_not_reached ();
1244 /* Avoid system error message boxes. */
1245 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1248 mono_perfcounters_init ();
1250 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1251 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1252 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1254 mono_gc_base_init ();
1256 MONO_FAST_TLS_INIT (tls_appdomain);
1257 appdomain_thread_id = TlsAlloc ();
1259 InitializeCriticalSection (&appdomains_mutex);
1261 mono_metadata_init ();
1262 mono_images_init ();
1263 mono_assemblies_init ();
1264 mono_classes_init ();
1265 mono_loader_init ();
1266 mono_reflection_init ();
1268 /* FIXME: When should we release this memory? */
1269 MONO_GC_REGISTER_ROOT_FIXED (appdomains_list);
1271 domain = mono_domain_create ();
1272 mono_root_domain = domain;
1274 SET_APPDOMAIN (domain);
1276 /* Get a list of runtimes supported by the exe */
1277 if (exe_filename != NULL) {
1279 * This function will load the exe file as a MonoImage. We need to close it, but
1280 * that would mean it would be reloaded later. So instead, we save it to
1281 * exe_image, and close it during shutdown.
1283 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1286 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1288 exe_image = mono_image_open (exe_filename, NULL);
1290 mono_fixup_exe_image (exe_image);
1292 } else if (runtime_version != NULL) {
1293 runtimes [0] = get_runtime_by_version (runtime_version);
1294 runtimes [1] = NULL;
1297 if (runtimes [0] == NULL) {
1298 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1299 runtimes [0] = default_runtime;
1300 runtimes [1] = NULL;
1301 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1302 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1305 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1306 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1307 current_runtime = runtimes [n];
1308 ass = mono_assembly_load_corlib (current_runtime, &status);
1309 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1314 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1316 case MONO_IMAGE_ERROR_ERRNO: {
1317 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1318 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1319 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1320 g_free (corlib_file);
1323 case MONO_IMAGE_IMAGE_INVALID:
1324 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1325 mono_assembly_getrootdir ());
1327 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1328 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1329 mono_assembly_getrootdir ());
1332 /* to suppress compiler warning */
1338 mono_defaults.corlib = mono_assembly_get_image (ass);
1340 mono_defaults.object_class = mono_class_from_name (
1341 mono_defaults.corlib, "System", "Object");
1342 g_assert (mono_defaults.object_class != 0);
1344 mono_defaults.void_class = mono_class_from_name (
1345 mono_defaults.corlib, "System", "Void");
1346 g_assert (mono_defaults.void_class != 0);
1348 mono_defaults.boolean_class = mono_class_from_name (
1349 mono_defaults.corlib, "System", "Boolean");
1350 g_assert (mono_defaults.boolean_class != 0);
1352 mono_defaults.byte_class = mono_class_from_name (
1353 mono_defaults.corlib, "System", "Byte");
1354 g_assert (mono_defaults.byte_class != 0);
1356 mono_defaults.sbyte_class = mono_class_from_name (
1357 mono_defaults.corlib, "System", "SByte");
1358 g_assert (mono_defaults.sbyte_class != 0);
1360 mono_defaults.int16_class = mono_class_from_name (
1361 mono_defaults.corlib, "System", "Int16");
1362 g_assert (mono_defaults.int16_class != 0);
1364 mono_defaults.uint16_class = mono_class_from_name (
1365 mono_defaults.corlib, "System", "UInt16");
1366 g_assert (mono_defaults.uint16_class != 0);
1368 mono_defaults.int32_class = mono_class_from_name (
1369 mono_defaults.corlib, "System", "Int32");
1370 g_assert (mono_defaults.int32_class != 0);
1372 mono_defaults.uint32_class = mono_class_from_name (
1373 mono_defaults.corlib, "System", "UInt32");
1374 g_assert (mono_defaults.uint32_class != 0);
1376 mono_defaults.uint_class = mono_class_from_name (
1377 mono_defaults.corlib, "System", "UIntPtr");
1378 g_assert (mono_defaults.uint_class != 0);
1380 mono_defaults.int_class = mono_class_from_name (
1381 mono_defaults.corlib, "System", "IntPtr");
1382 g_assert (mono_defaults.int_class != 0);
1384 mono_defaults.int64_class = mono_class_from_name (
1385 mono_defaults.corlib, "System", "Int64");
1386 g_assert (mono_defaults.int64_class != 0);
1388 mono_defaults.uint64_class = mono_class_from_name (
1389 mono_defaults.corlib, "System", "UInt64");
1390 g_assert (mono_defaults.uint64_class != 0);
1392 mono_defaults.single_class = mono_class_from_name (
1393 mono_defaults.corlib, "System", "Single");
1394 g_assert (mono_defaults.single_class != 0);
1396 mono_defaults.double_class = mono_class_from_name (
1397 mono_defaults.corlib, "System", "Double");
1398 g_assert (mono_defaults.double_class != 0);
1400 mono_defaults.char_class = mono_class_from_name (
1401 mono_defaults.corlib, "System", "Char");
1402 g_assert (mono_defaults.char_class != 0);
1404 mono_defaults.string_class = mono_class_from_name (
1405 mono_defaults.corlib, "System", "String");
1406 g_assert (mono_defaults.string_class != 0);
1408 mono_defaults.enum_class = mono_class_from_name (
1409 mono_defaults.corlib, "System", "Enum");
1410 g_assert (mono_defaults.enum_class != 0);
1412 mono_defaults.array_class = mono_class_from_name (
1413 mono_defaults.corlib, "System", "Array");
1414 g_assert (mono_defaults.array_class != 0);
1416 mono_defaults.delegate_class = mono_class_from_name (
1417 mono_defaults.corlib, "System", "Delegate");
1418 g_assert (mono_defaults.delegate_class != 0 );
1420 mono_defaults.multicastdelegate_class = mono_class_from_name (
1421 mono_defaults.corlib, "System", "MulticastDelegate");
1422 g_assert (mono_defaults.multicastdelegate_class != 0 );
1424 mono_defaults.asyncresult_class = mono_class_from_name (
1425 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1427 g_assert (mono_defaults.asyncresult_class != 0 );
1429 mono_defaults.manualresetevent_class = mono_class_from_name (
1430 mono_defaults.corlib, "System.Threading", "ManualResetEvent");
1431 g_assert (mono_defaults.manualresetevent_class != 0 );
1433 mono_defaults.typehandle_class = mono_class_from_name (
1434 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1435 g_assert (mono_defaults.typehandle_class != 0);
1437 mono_defaults.methodhandle_class = mono_class_from_name (
1438 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1439 g_assert (mono_defaults.methodhandle_class != 0);
1441 mono_defaults.fieldhandle_class = mono_class_from_name (
1442 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1443 g_assert (mono_defaults.fieldhandle_class != 0);
1445 mono_defaults.systemtype_class = mono_class_from_name (
1446 mono_defaults.corlib, "System", "Type");
1447 g_assert (mono_defaults.systemtype_class != 0);
1449 mono_defaults.monotype_class = mono_class_from_name (
1450 mono_defaults.corlib, "System", "MonoType");
1451 g_assert (mono_defaults.monotype_class != 0);
1453 mono_defaults.exception_class = mono_class_from_name (
1454 mono_defaults.corlib, "System", "Exception");
1455 g_assert (mono_defaults.exception_class != 0);
1457 mono_defaults.threadabortexception_class = mono_class_from_name (
1458 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1459 g_assert (mono_defaults.threadabortexception_class != 0);
1461 mono_defaults.thread_class = mono_class_from_name (
1462 mono_defaults.corlib, "System.Threading", "Thread");
1463 g_assert (mono_defaults.thread_class != 0);
1465 mono_defaults.internal_thread_class = mono_class_from_name (
1466 mono_defaults.corlib, "System.Threading", "InternalThread");
1467 if (!mono_defaults.internal_thread_class) {
1468 /* This can happen with an old mscorlib */
1469 fprintf (stderr, "Corlib too old for this runtime.\n");
1470 fprintf (stderr, "Loaded from: %s\n",
1471 mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown");
1475 mono_defaults.appdomain_class = mono_class_from_name (
1476 mono_defaults.corlib, "System", "AppDomain");
1477 g_assert (mono_defaults.appdomain_class != 0);
1479 mono_defaults.transparent_proxy_class = mono_class_from_name (
1480 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1481 g_assert (mono_defaults.transparent_proxy_class != 0);
1483 mono_defaults.real_proxy_class = mono_class_from_name (
1484 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1485 g_assert (mono_defaults.real_proxy_class != 0);
1487 mono_defaults.mono_method_message_class = mono_class_from_name (
1488 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1489 g_assert (mono_defaults.mono_method_message_class != 0);
1491 mono_defaults.field_info_class = mono_class_from_name (
1492 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1493 g_assert (mono_defaults.field_info_class != 0);
1495 mono_defaults.method_info_class = mono_class_from_name (
1496 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1497 g_assert (mono_defaults.method_info_class != 0);
1499 mono_defaults.stringbuilder_class = mono_class_from_name (
1500 mono_defaults.corlib, "System.Text", "StringBuilder");
1501 g_assert (mono_defaults.stringbuilder_class != 0);
1503 mono_defaults.math_class = mono_class_from_name (
1504 mono_defaults.corlib, "System", "Math");
1505 g_assert (mono_defaults.math_class != 0);
1507 mono_defaults.stack_frame_class = mono_class_from_name (
1508 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1509 g_assert (mono_defaults.stack_frame_class != 0);
1511 mono_defaults.stack_trace_class = mono_class_from_name (
1512 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1513 g_assert (mono_defaults.stack_trace_class != 0);
1515 mono_defaults.marshal_class = mono_class_from_name (
1516 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1517 g_assert (mono_defaults.marshal_class != 0);
1519 mono_defaults.iserializeable_class = mono_class_from_name (
1520 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1521 g_assert (mono_defaults.iserializeable_class != 0);
1523 mono_defaults.serializationinfo_class = mono_class_from_name (
1524 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1525 g_assert (mono_defaults.serializationinfo_class != 0);
1527 mono_defaults.streamingcontext_class = mono_class_from_name (
1528 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1529 g_assert (mono_defaults.streamingcontext_class != 0);
1531 mono_defaults.typed_reference_class = mono_class_from_name (
1532 mono_defaults.corlib, "System", "TypedReference");
1533 g_assert (mono_defaults.typed_reference_class != 0);
1535 mono_defaults.argumenthandle_class = mono_class_from_name (
1536 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1537 g_assert (mono_defaults.argumenthandle_class != 0);
1539 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1540 mono_defaults.corlib, "System", "MarshalByRefObject");
1541 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1543 mono_defaults.monitor_class = mono_class_from_name (
1544 mono_defaults.corlib, "System.Threading", "Monitor");
1545 g_assert (mono_defaults.monitor_class != 0);
1547 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1548 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1549 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1551 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1552 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1554 mono_defaults.executioncontext_class = mono_class_from_name (
1555 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1557 mono_defaults.internals_visible_class = mono_class_from_name (
1558 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1560 mono_defaults.critical_finalizer_object = mono_class_from_name (
1561 mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
1564 * mscorlib needs a little help, only now it can load its friends list (after we have
1565 * loaded the InternalsVisibleToAttribute), load it now
1567 mono_assembly_load_friends (ass);
1569 mono_defaults.safehandle_class = mono_class_from_name (
1570 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1572 mono_defaults.handleref_class = mono_class_from_name (
1573 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1575 mono_defaults.attribute_class = mono_class_from_name (
1576 mono_defaults.corlib, "System", "Attribute");
1578 mono_defaults.customattribute_data_class = mono_class_from_name (
1579 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1581 /* these are initialized lazily when COM features are used */
1582 mono_defaults.variant_class = NULL;
1583 mono_defaults.com_object_class = NULL;
1584 mono_defaults.com_interop_proxy_class = NULL;
1585 mono_defaults.iunknown_class = NULL;
1586 mono_defaults.idispatch_class = NULL;
1589 * Note that mono_defaults.generic_*_class is only non-NULL if we're
1590 * using the 2.0 corlib.
1592 mono_class_init (mono_defaults.array_class);
1593 mono_defaults.generic_nullable_class = mono_class_from_name (
1594 mono_defaults.corlib, "System", "Nullable`1");
1595 mono_defaults.generic_ilist_class = mono_class_from_name (
1596 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1598 domain->friendly_name = g_path_get_basename (filename);
1600 _mono_debug_init_corlib (domain);
1608 * Creates the initial application domain and initializes the mono_defaults
1610 * This function is guaranteed to not run any IL code.
1611 * The runtime is initialized using the default runtime version.
1613 * Returns: the initial domain.
1616 mono_init (const char *domain_name)
1618 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1622 * mono_init_from_assembly:
1623 * @domain_name: name to give to the initial domain
1624 * @filename: filename to load on startup
1626 * Used by the runtime, users should use mono_jit_init instead.
1628 * Creates the initial application domain and initializes the mono_defaults
1630 * This function is guaranteed to not run any IL code.
1631 * The runtime is initialized using the runtime version required by the
1632 * provided executable. The version is determined by looking at the exe
1633 * configuration file and the version PE field)
1635 * Returns: the initial domain.
1638 mono_init_from_assembly (const char *domain_name, const char *filename)
1640 return mono_init_internal (domain_name, filename, NULL);
1644 * mono_init_version:
1646 * Used by the runtime, users should use mono_jit_init instead.
1648 * Creates the initial application domain and initializes the mono_defaults
1651 * This function is guaranteed to not run any IL code.
1652 * The runtime is initialized using the provided rutime version.
1654 * Returns: the initial domain.
1657 mono_init_version (const char *domain_name, const char *version)
1659 return mono_init_internal (domain_name, NULL, version);
1663 * mono_init_com_types:
1665 * Initializes all types needed for COM Interop in mono_defaults structure.
1668 mono_init_com_types (void)
1670 static gboolean initialized = FALSE;
1675 /* FIXME: do I need some threading protection here */
1677 g_assert (mono_defaults.corlib);
1679 mono_defaults.variant_class = mono_class_from_name (
1680 mono_defaults.corlib, "System", "Variant");
1681 g_assert (mono_defaults.variant_class != 0);
1683 mono_defaults.com_object_class = mono_class_from_name (
1684 mono_defaults.corlib, "System", "__ComObject");
1685 g_assert (mono_defaults.com_object_class != 0);
1687 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1688 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1689 g_assert (mono_defaults.com_interop_proxy_class != 0);
1691 mono_defaults.iunknown_class = mono_class_from_name (
1692 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1693 g_assert (mono_defaults.iunknown_class != 0);
1695 mono_defaults.idispatch_class = mono_class_from_name (
1696 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1697 g_assert (mono_defaults.idispatch_class != 0);
1705 * Cleans up all metadata modules.
1710 mono_close_exe_image ();
1712 mono_defaults.corlib = NULL;
1714 mono_config_cleanup ();
1715 mono_loader_cleanup ();
1716 mono_classes_cleanup ();
1717 mono_assemblies_cleanup ();
1718 mono_images_cleanup ();
1719 mono_debug_cleanup ();
1720 mono_metadata_cleanup ();
1722 TlsFree (appdomain_thread_id);
1723 DeleteCriticalSection (&appdomains_mutex);
1726 * This should be called last as TlsGetValue ()/TlsSetValue () can be called during
1735 mono_close_exe_image (void)
1738 mono_image_close (exe_image);
1742 * mono_get_root_domain:
1744 * The root AppDomain is the initial domain created by the runtime when it is
1745 * initialized. Programs execute on this AppDomain, but can create new ones
1746 * later. Currently there is no unmanaged API to create new AppDomains, this
1747 * must be done from managed code.
1749 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1752 mono_get_root_domain (void)
1754 return mono_root_domain;
1760 * Returns: the current domain, to obtain the root domain use
1761 * mono_get_root_domain().
1766 return GET_APPDOMAIN ();
1770 mono_domain_unset (void)
1772 SET_APPDOMAIN (NULL);
1776 mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception)
1778 MonoInternalThread *thread;
1780 if (mono_domain_get () == domain)
1783 SET_APPDOMAIN (domain);
1784 SET_APPCONTEXT (domain->default_context);
1786 if (migrate_exception) {
1787 thread = mono_thread_internal_current ();
1788 if (!thread->abort_exc)
1791 g_assert (thread->abort_exc->object.vtable->domain != domain);
1792 MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
1793 g_assert (thread->abort_exc->object.vtable->domain == domain);
1798 * mono_domain_set_internal:
1799 * @domain: the new domain
1801 * Sets the current domain to @domain.
1804 mono_domain_set_internal (MonoDomain *domain)
1806 mono_domain_set_internal_with_options (domain, TRUE);
1810 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1816 * Create a copy of the data to avoid calling the user callback
1817 * inside the lock because that could lead to deadlocks.
1818 * We can do this because this function is not perf. critical.
1820 mono_appdomains_lock ();
1821 size = appdomain_list_size;
1822 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1823 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1824 mono_appdomains_unlock ();
1826 for (i = 0; i < size; ++i) {
1828 func (copy [i], user_data);
1831 mono_gc_free_fixed (copy);
1835 * mono_domain_assembly_open:
1836 * @domain: the application domain
1837 * @name: file name of the assembly
1839 * fixme: maybe we should integrate this with mono_assembly_open ??
1842 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1844 MonoDomain *current;
1848 mono_domain_assemblies_lock (domain);
1849 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1851 if (strcmp (name, ass->aname.name) == 0) {
1852 mono_domain_assemblies_unlock (domain);
1856 mono_domain_assemblies_unlock (domain);
1858 if (domain != mono_domain_get ()) {
1859 current = mono_domain_get ();
1861 mono_domain_set (domain, FALSE);
1862 ass = mono_assembly_open (name, NULL);
1863 mono_domain_set (current, FALSE);
1865 ass = mono_assembly_open (name, NULL);
1872 free_slist (gpointer key, gpointer value, gpointer user_data)
1874 g_slist_free (value);
1878 unregister_vtable_reflection_type (MonoVTable *vtable)
1880 MonoObject *type = vtable->type;
1882 if (type->vtable->klass != mono_defaults.monotype_class)
1883 MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type);
1887 mono_domain_free (MonoDomain *domain, gboolean force)
1889 int code_size, code_alloc;
1891 if ((domain == mono_root_domain) && !force) {
1892 g_warning ("cant unload root domain");
1896 if (mono_dont_free_domains)
1899 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1901 mono_debug_domain_unload (domain);
1903 mono_appdomains_lock ();
1904 appdomains_list [domain->domain_id] = NULL;
1905 mono_appdomains_unlock ();
1907 /* must do this early as it accesses fields and types */
1908 if (domain->special_static_fields) {
1909 mono_alloc_special_static_data_free (domain->special_static_fields);
1910 g_hash_table_destroy (domain->special_static_fields);
1911 domain->special_static_fields = NULL;
1915 * We must destroy all these hash tables here because they
1916 * contain references to managed objects belonging to the
1917 * domain. Once we let the GC clear the domain there must be
1918 * no more such references, or we'll crash if a collection
1921 mono_g_hash_table_destroy (domain->ldstr_table);
1922 domain->ldstr_table = NULL;
1924 mono_g_hash_table_destroy (domain->env);
1927 if (domain->tlsrec_list) {
1928 mono_thread_destroy_domain_tls (domain);
1929 domain->tlsrec_list = NULL;
1932 mono_reflection_cleanup_domain (domain);
1934 if (domain->type_hash) {
1935 mono_g_hash_table_destroy (domain->type_hash);
1936 domain->type_hash = NULL;
1938 if (domain->type_init_exception_hash) {
1939 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1940 domain->type_init_exception_hash = NULL;
1943 if (domain->class_vtable_array) {
1945 for (i = 0; i < domain->class_vtable_array->len; ++i)
1946 unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i));
1949 /* This needs to be done before closing assemblies */
1950 mono_gc_clear_domain (domain);
1952 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1953 MonoAssembly *ass = tmp->data;
1954 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);
1955 if (!mono_assembly_close_except_image_pools (ass))
1959 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1960 MonoAssembly *ass = tmp->data;
1962 mono_assembly_close_finish (ass);
1964 g_slist_free (domain->domain_assemblies);
1965 domain->domain_assemblies = NULL;
1968 * Send this after the assemblies have been unloaded and the domain is still in a
1971 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
1973 if (free_domain_hook)
1974 free_domain_hook (domain);
1976 /* FIXME: free delegate_hash_table when it's used */
1977 if (domain->search_path) {
1978 g_strfreev (domain->search_path);
1979 domain->search_path = NULL;
1981 domain->create_proxy_for_type_method = NULL;
1982 domain->private_invoke_method = NULL;
1983 domain->default_context = NULL;
1984 domain->out_of_memory_ex = NULL;
1985 domain->null_reference_ex = NULL;
1986 domain->stack_overflow_ex = NULL;
1987 domain->ephemeron_tombstone = NULL;
1988 domain->entry_assembly = NULL;
1990 g_free (domain->friendly_name);
1991 domain->friendly_name = NULL;
1992 g_ptr_array_free (domain->class_vtable_array, TRUE);
1993 domain->class_vtable_array = NULL;
1994 g_hash_table_destroy (domain->proxy_vtable_hash);
1995 domain->proxy_vtable_hash = NULL;
1996 if (domain->static_data_array) {
1997 mono_gc_free_fixed (domain->static_data_array);
1998 domain->static_data_array = NULL;
2000 mono_internal_hash_table_destroy (&domain->jit_code_hash);
2003 * There might still be jit info tables of this domain which
2004 * are not freed. Since the domain cannot be in use anymore,
2005 * this will free them.
2007 mono_thread_hazardous_try_free_all ();
2008 g_assert (domain->num_jit_info_tables == 1);
2009 jit_info_table_free (domain->jit_info_table);
2010 domain->jit_info_table = NULL;
2011 g_assert (!domain->jit_info_free_queue);
2013 /* collect statistics */
2014 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
2015 total_domain_code_alloc += code_alloc;
2016 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
2017 max_domain_code_size = MAX (max_domain_code_size, code_size);
2019 #ifdef DEBUG_DOMAIN_UNLOAD
2020 mono_mempool_invalidate (domain->mp);
2021 mono_code_manager_invalidate (domain->code_mp);
2023 mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
2024 mono_mempool_destroy (domain->mp);
2026 mono_code_manager_destroy (domain->code_mp);
2027 domain->code_mp = NULL;
2030 g_hash_table_destroy (domain->finalizable_objects_hash);
2031 domain->finalizable_objects_hash = NULL;
2032 if (domain->track_resurrection_objects_hash) {
2033 g_hash_table_foreach (domain->track_resurrection_objects_hash, free_slist, NULL);
2034 g_hash_table_destroy (domain->track_resurrection_objects_hash);
2036 if (domain->track_resurrection_handles_hash)
2037 g_hash_table_destroy (domain->track_resurrection_handles_hash);
2038 if (domain->method_rgctx_hash) {
2039 g_hash_table_destroy (domain->method_rgctx_hash);
2040 domain->method_rgctx_hash = NULL;
2042 if (domain->generic_virtual_cases) {
2043 g_hash_table_destroy (domain->generic_virtual_cases);
2044 domain->generic_virtual_cases = NULL;
2046 if (domain->generic_virtual_thunks) {
2047 g_hash_table_destroy (domain->generic_virtual_thunks);
2048 domain->generic_virtual_thunks = NULL;
2050 if (domain->ftnptrs_hash) {
2051 g_hash_table_destroy (domain->ftnptrs_hash);
2052 domain->ftnptrs_hash = NULL;
2055 DeleteCriticalSection (&domain->finalizable_objects_hash_lock);
2056 DeleteCriticalSection (&domain->assemblies_lock);
2057 DeleteCriticalSection (&domain->jit_code_hash_lock);
2058 DeleteCriticalSection (&domain->lock);
2059 domain->setup = NULL;
2061 mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
2063 /* FIXME: anything else required ? */
2065 mono_gc_free_fixed (domain);
2067 mono_perfcounters->loader_appdomains--;
2069 if ((domain == mono_root_domain))
2070 mono_root_domain = NULL;
2074 * mono_domain_get_id:
2077 * Returns: the a domain for a specific domain id.
2080 mono_domain_get_by_id (gint32 domainid)
2082 MonoDomain * domain;
2084 mono_appdomains_lock ();
2085 if (domainid < appdomain_list_size)
2086 domain = appdomains_list [domainid];
2089 mono_appdomains_unlock ();
2095 mono_domain_get_id (MonoDomain *domain)
2097 return domain->domain_id;
2101 * mono_domain_alloc:
2103 * LOCKING: Acquires the domain lock.
2106 mono_domain_alloc (MonoDomain *domain, guint size)
2110 mono_domain_lock (domain);
2111 mono_perfcounters->loader_bytes += size;
2112 res = mono_mempool_alloc (domain->mp, size);
2113 mono_domain_unlock (domain);
2119 * mono_domain_alloc0:
2121 * LOCKING: Acquires the domain lock.
2124 mono_domain_alloc0 (MonoDomain *domain, guint size)
2128 mono_domain_lock (domain);
2129 mono_perfcounters->loader_bytes += size;
2130 res = mono_mempool_alloc0 (domain->mp, size);
2131 mono_domain_unlock (domain);
2137 * mono_domain_code_reserve:
2139 * LOCKING: Acquires the domain lock.
2142 mono_domain_code_reserve (MonoDomain *domain, int size)
2146 mono_domain_lock (domain);
2147 res = mono_code_manager_reserve (domain->code_mp, size);
2148 mono_domain_unlock (domain);
2154 * mono_domain_code_reserve_align:
2156 * LOCKING: Acquires the domain lock.
2159 mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment)
2163 mono_domain_lock (domain);
2164 res = mono_code_manager_reserve_align (domain->code_mp, size, alignment);
2165 mono_domain_unlock (domain);
2171 * mono_domain_code_commit:
2173 * LOCKING: Acquires the domain lock.
2176 mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize)
2178 mono_domain_lock (domain);
2179 mono_code_manager_commit (domain->code_mp, data, size, newsize);
2180 mono_domain_unlock (domain);
2183 #if defined(__native_client_codegen__) && defined(__native_client__)
2185 * Given the temporary buffer (allocated by mono_domain_code_reserve) into which
2186 * we are generating code, return a pointer to the destination in the dynamic
2187 * code segment into which the code will be copied when mono_domain_code_commit
2189 * LOCKING: Acquires the domain lock.
2192 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2195 mono_domain_lock (domain);
2196 dest = nacl_code_manager_get_code_dest (domain->code_mp, data);
2197 mono_domain_unlock (domain);
2202 * Convenience function which calls mono_domain_code_commit to validate and copy
2203 * the code. The caller sets *buf_base and *buf_size to the start and size of
2204 * the buffer (allocated by mono_domain_code_reserve), and *code_end to the byte
2205 * after the last instruction byte. On return, *buf_base will point to the start
2206 * of the copied in the code segment, and *code_end will point after the end of
2210 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2212 guint8 *tmp = nacl_domain_get_code_dest (domain, *buf_base);
2213 mono_domain_code_commit (domain, *buf_base, buf_size, *code_end - *buf_base);
2214 *code_end = tmp + (*code_end - *buf_base);
2220 /* no-op versions of Native Client functions */
2223 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2229 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2236 * mono_domain_code_foreach:
2237 * Iterate over the code thunks of the code manager of @domain.
2239 * The @func callback MUST not take any locks. If it really needs to, it must respect
2240 * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety
2241 * LOCKING: Acquires the domain lock.
2245 mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data)
2247 mono_domain_lock (domain);
2248 mono_code_manager_foreach (domain->code_mp, func, user_data);
2249 mono_domain_unlock (domain);
2254 mono_context_set (MonoAppContext * new_context)
2256 SET_APPCONTEXT (new_context);
2260 mono_context_get (void)
2262 return GET_APPCONTEXT ();
2265 /* LOCKING: the caller holds the lock for this domain */
2267 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
2269 /* The first entry in the array is the index of the next free slot
2270 * and the total size of the array
2273 if (domain->static_data_array) {
2274 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
2275 next = GPOINTER_TO_INT (domain->static_data_array [0]);
2277 /* 'data' is allocated by alloc_fixed */
2278 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2));
2279 memcpy (new_array, domain->static_data_array, sizeof (gpointer) * size);
2281 new_array [1] = GINT_TO_POINTER (size);
2282 mono_gc_free_fixed (domain->static_data_array);
2283 domain->static_data_array = new_array;
2287 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, MONO_GC_ROOT_DESCR_FOR_FIXED (size));
2289 new_array [0] = GINT_TO_POINTER (next);
2290 new_array [1] = GINT_TO_POINTER (size);
2291 domain->static_data_array = new_array;
2293 domain->static_data_array [next++] = data;
2294 domain->static_data_array [0] = GINT_TO_POINTER (next);
2298 mono_get_corlib (void)
2300 return mono_defaults.corlib;
2304 mono_get_object_class (void)
2306 return mono_defaults.object_class;
2310 mono_get_byte_class (void)
2312 return mono_defaults.byte_class;
2316 mono_get_void_class (void)
2318 return mono_defaults.void_class;
2322 mono_get_boolean_class (void)
2324 return mono_defaults.boolean_class;
2328 mono_get_sbyte_class (void)
2330 return mono_defaults.sbyte_class;
2334 mono_get_int16_class (void)
2336 return mono_defaults.int16_class;
2340 mono_get_uint16_class (void)
2342 return mono_defaults.uint16_class;
2346 mono_get_int32_class (void)
2348 return mono_defaults.int32_class;
2352 mono_get_uint32_class (void)
2354 return mono_defaults.uint32_class;
2358 mono_get_intptr_class (void)
2360 return mono_defaults.int_class;
2364 mono_get_uintptr_class (void)
2366 return mono_defaults.uint_class;
2370 mono_get_int64_class (void)
2372 return mono_defaults.int64_class;
2376 mono_get_uint64_class (void)
2378 return mono_defaults.uint64_class;
2382 mono_get_single_class (void)
2384 return mono_defaults.single_class;
2388 mono_get_double_class (void)
2390 return mono_defaults.double_class;
2394 mono_get_char_class (void)
2396 return mono_defaults.char_class;
2400 mono_get_string_class (void)
2402 return mono_defaults.string_class;
2406 mono_get_enum_class (void)
2408 return mono_defaults.enum_class;
2412 mono_get_array_class (void)
2414 return mono_defaults.array_class;
2418 mono_get_thread_class (void)
2420 return mono_defaults.thread_class;
2424 mono_get_exception_class (void)
2426 return mono_defaults.exception_class;
2430 static char* get_attribute_value (const gchar **attribute_names,
2431 const gchar **attribute_values,
2432 const char *att_name)
2435 for (n=0; attribute_names[n] != NULL; n++) {
2436 if (strcmp (attribute_names[n], att_name) == 0)
2437 return g_strdup (attribute_values[n]);
2442 static void start_element (GMarkupParseContext *context,
2443 const gchar *element_name,
2444 const gchar **attribute_names,
2445 const gchar **attribute_values,
2449 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2451 if (strcmp (element_name, "configuration") == 0) {
2452 app_config->configuration_count++;
2455 if (strcmp (element_name, "startup") == 0) {
2456 app_config->startup_count++;
2460 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2463 if (strcmp (element_name, "requiredRuntime") == 0) {
2464 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2465 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2466 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2467 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2471 static void end_element (GMarkupParseContext *context,
2472 const gchar *element_name,
2476 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2478 if (strcmp (element_name, "configuration") == 0) {
2479 app_config->configuration_count--;
2480 } else if (strcmp (element_name, "startup") == 0) {
2481 app_config->startup_count--;
2485 static const GMarkupParser
2494 static AppConfigInfo *
2495 app_config_parse (const char *exe_filename)
2497 AppConfigInfo *app_config;
2498 GMarkupParseContext *context;
2501 const char *bundled_config;
2502 char *config_filename;
2504 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2506 if (bundled_config) {
2507 text = g_strdup (bundled_config);
2508 len = strlen (text);
2510 config_filename = g_strconcat (exe_filename, ".config", NULL);
2512 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2513 g_free (config_filename);
2516 g_free (config_filename);
2519 app_config = g_new0 (AppConfigInfo, 1);
2521 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2522 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2523 g_markup_parse_context_end_parse (context, NULL);
2525 g_markup_parse_context_free (context);
2531 app_config_free (AppConfigInfo* app_config)
2534 GSList *list = app_config->supported_runtimes;
2535 while (list != NULL) {
2536 rt = (char*)list->data;
2538 list = g_slist_next (list);
2540 g_slist_free (app_config->supported_runtimes);
2541 g_free (app_config->required_runtime);
2542 g_free (app_config);
2546 static const MonoRuntimeInfo*
2547 get_runtime_by_version (const char *version)
2550 int max = G_N_ELEMENTS (supported_runtimes);
2551 gboolean do_partial_match;
2557 vlen = strlen (version);
2558 if (vlen >= 4 && version [1] - '0' >= 4)
2559 do_partial_match = TRUE;
2561 do_partial_match = FALSE;
2563 for (n=0; n<max; n++) {
2564 if (do_partial_match && strncmp (version, supported_runtimes[n].runtime_version, vlen) == 0)
2565 return &supported_runtimes[n];
2566 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2567 return &supported_runtimes[n];
2573 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2575 AppConfigInfo* app_config;
2577 const MonoRuntimeInfo* runtime = NULL;
2578 MonoImage *image = NULL;
2580 app_config = app_config_parse (exe_file);
2582 if (app_config != NULL) {
2583 /* Check supportedRuntime elements, if none is supported, fail.
2584 * If there are no such elements, look for a requiredRuntime element.
2586 if (app_config->supported_runtimes != NULL) {
2588 GSList *list = app_config->supported_runtimes;
2589 while (list != NULL) {
2590 version = (char*) list->data;
2591 runtime = get_runtime_by_version (version);
2592 if (runtime != NULL)
2593 runtimes [n++] = runtime;
2594 list = g_slist_next (list);
2596 runtimes [n] = NULL;
2597 app_config_free (app_config);
2601 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2602 if (app_config->required_runtime != NULL) {
2603 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2604 runtimes [1] = NULL;
2605 app_config_free (app_config);
2608 app_config_free (app_config);
2611 /* Look for a runtime with the exact version */
2612 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2615 image = mono_image_open (exe_file, NULL);
2617 if (image == NULL) {
2618 /* The image is wrong or the file was not found. In this case return
2619 * a default runtime and leave to the initialization method the work of
2620 * reporting the error.
2622 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2623 runtimes [1] = NULL;
2629 runtimes [0] = get_runtime_by_version (image->version);
2630 runtimes [1] = NULL;
2635 * mono_get_runtime_info:
2637 * Returns: the version of the current runtime instance.
2639 const MonoRuntimeInfo*
2640 mono_get_runtime_info (void)
2642 return current_runtime;
2646 mono_debugger_check_runtime_version (const char *filename)
2648 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2649 const MonoRuntimeInfo *rinfo;
2652 get_runtimes_from_exe (filename, &image, runtimes);
2653 rinfo = runtimes [0];
2656 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2658 if (rinfo != current_runtime)
2659 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2660 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2661 filename, rinfo->runtime_version);
2667 * mono_framework_version:
2669 * Return the major version of the framework curently executing.
2672 mono_framework_version (void)
2674 return current_runtime->framework_version [0] - '0';