2 * domain.c: MonoDomain functions
5 * Dietmar Maurer (dietmar@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
17 #include <mono/metadata/gc-internal.h>
19 #include <mono/utils/mono-compiler.h>
20 #include <mono/utils/mono-logger.h>
21 #include <mono/utils/mono-membar.h>
22 #include <mono/utils/mono-counters.h>
23 #include <mono/metadata/object.h>
24 #include <mono/metadata/object-internals.h>
25 #include <mono/metadata/domain-internals.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/assembly.h>
28 #include <mono/metadata/exception.h>
29 #include <mono/metadata/metadata-internals.h>
30 #include <mono/metadata/gc-internal.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-debug-debugger.h>
33 #include <mono/metadata/mono-config.h>
34 #include <mono/metadata/threads-types.h>
35 #include <metadata/threads.h>
36 #include <metadata/profiler-private.h>
37 #include <mono/metadata/coree.h>
39 /* #define DEBUG_DOMAIN_UNLOAD */
41 /* we need to use both the Tls* functions and __thread because
42 * some archs may generate faster jit code with one meachanism
43 * or the other (we used to do it because tls slots were GC-tracked,
44 * but we can't depend on this).
46 static guint32 appdomain_thread_id = -1;
49 static __thread MonoDomain * tls_appdomain MONO_TLS_FAST;
50 #define GET_APPDOMAIN() tls_appdomain
51 #define SET_APPDOMAIN(x) do { \
53 TlsSetValue (appdomain_thread_id, x); \
58 #define GET_APPDOMAIN() ((MonoDomain *)TlsGetValue (appdomain_thread_id))
59 #define SET_APPDOMAIN(x) TlsSetValue (appdomain_thread_id, x);
63 #define GET_APPCONTEXT() (mono_thread_current ()->current_appcontext)
64 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_current (), current_appcontext, (x))
66 static guint16 appdomain_list_size = 0;
67 static guint16 appdomain_next = 0;
68 static MonoDomain **appdomains_list = NULL;
69 static MonoImage *exe_image;
71 gboolean mono_dont_free_domains;
73 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
74 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
75 static CRITICAL_SECTION appdomains_mutex;
77 static MonoDomain *mono_root_domain = NULL;
80 static int max_domain_code_size = 0;
81 static int max_domain_code_alloc = 0;
82 static int total_domain_code_alloc = 0;
84 /* AppConfigInfo: Information about runtime versions supported by an
88 GSList *supported_runtimes;
89 char *required_runtime;
90 int configuration_count;
95 * AotModuleInfo: Contains information about AOT modules.
102 static const MonoRuntimeInfo *current_runtime = NULL;
104 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
107 * Contains information about AOT loaded code.
109 static MonoAotModuleInfoTable *aot_modules = NULL;
111 /* This is the list of runtime versions supported by this JIT.
113 static const MonoRuntimeInfo supported_runtimes[] = {
114 {"v1.0.3705", "1.0", { {1,0,5000,0}, {7,0,5000,0} } },
115 {"v1.1.4322", "1.0", { {1,0,5000,0}, {7,0,5000,0} } },
116 {"v2.0.50215","2.0", { {2,0,0,0}, {8,0,0,0} } },
117 {"v2.0.50727","2.0", { {2,0,0,0}, {8,0,0,0} } },
118 {"moonlight", "2.1", { {2,0,5,0}, {9,0,0,0} } },
122 /* The stable runtime version */
123 #define DEFAULT_RUNTIME_VERSION "v1.1.4322"
125 /* Callbacks installed by the JIT */
126 static MonoCreateDomainFunc create_domain_hook;
127 static MonoFreeDomainFunc free_domain_hook;
129 /* This is intentionally not in the header file, so people don't misuse it. */
130 extern void _mono_debug_init_corlib (MonoDomain *domain);
133 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
135 static const MonoRuntimeInfo*
136 get_runtime_by_version (const char *version);
139 mono_jit_info_find_aot_module (guint8* addr);
142 mono_domain_get_tls_key (void)
144 return appdomain_thread_id;
148 mono_domain_get_tls_offset (void)
151 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
152 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
157 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
158 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
159 #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)
161 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
162 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
164 #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
165 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
167 #define JIT_INFO_TABLE_HAZARD_INDEX 0
168 #define JIT_INFO_HAZARD_INDEX 1
171 jit_info_table_num_elements (MonoJitInfoTable *table)
174 int num_elements = 0;
176 for (i = 0; i < table->num_chunks; ++i) {
177 MonoJitInfoTableChunk *chunk = table->chunks [i];
178 int chunk_num_elements = chunk->num_elements;
181 for (j = 0; j < chunk_num_elements; ++j) {
182 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
190 static MonoJitInfoTableChunk*
191 jit_info_table_new_chunk (void)
193 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
199 static MonoJitInfoTable *
200 jit_info_table_new (MonoDomain *domain)
202 MonoJitInfoTable *table = g_malloc0 (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*));
204 table->domain = domain;
205 table->num_chunks = 1;
206 table->chunks [0] = jit_info_table_new_chunk ();
212 jit_info_table_free (MonoJitInfoTable *table)
215 int num_chunks = table->num_chunks;
216 MonoDomain *domain = table->domain;
218 mono_domain_lock (domain);
220 table->domain->num_jit_info_tables--;
221 if (table->domain->num_jit_info_tables <= 1) {
224 for (list = table->domain->jit_info_free_queue; list; list = list->next)
227 g_slist_free (table->domain->jit_info_free_queue);
228 table->domain->jit_info_free_queue = NULL;
231 /* At this point we assume that there are no other threads
232 still accessing the table, so we don't have to worry about
233 hazardous pointers. */
235 for (i = 0; i < num_chunks; ++i) {
236 MonoJitInfoTableChunk *chunk = table->chunks [i];
240 if (--chunk->refcount > 0)
243 num_elements = chunk->num_elements;
244 for (j = 0; j < num_elements; ++j) {
245 MonoJitInfo *ji = chunk->data [j];
247 if (IS_JIT_INFO_TOMBSTONE (ji))
254 mono_domain_unlock (domain);
259 /* Can be called with hp==NULL, in which case it acts as an ordinary
260 pointer fetch. It's used that way indirectly from
261 mono_jit_info_table_add(), which doesn't have to care about hazards
262 because it holds the respective domain lock. */
264 get_hazardous_pointer (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index)
269 /* Get the pointer */
271 /* If we don't have hazard pointers just return the
275 /* Make it hazardous */
276 mono_hazard_pointer_set (hp, hazard_index, p);
277 /* Check that it's still the same. If not, try
280 mono_hazard_pointer_clear (hp, hazard_index);
289 /* The jit_info_table is sorted in ascending order by the end
290 * addresses of the compiled methods. The reason why we have to do
291 * this is that once we introduce tombstones, it becomes possible for
292 * code ranges to overlap, and if we sort by code start and insert at
293 * the back of the table, we cannot guarantee that we won't overlook
296 * There are actually two possible ways to do the sorting and
297 * inserting which work with our lock-free mechanism:
299 * 1. Sort by start address and insert at the front. When looking for
300 * an entry, find the last one with a start address lower than the one
301 * you're looking for, then work your way to the front of the table.
303 * 2. Sort by end address and insert at the back. When looking for an
304 * entry, find the first one with an end address higher than the one
305 * you're looking for, then work your way to the end of the table.
307 * We chose the latter out of convenience.
310 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
312 int left = 0, right = table->num_chunks;
314 g_assert (left < right);
317 int pos = (left + right) / 2;
318 MonoJitInfoTableChunk *chunk = table->chunks [pos];
320 if (addr < chunk->last_code_end)
324 } while (left < right);
325 g_assert (left == right);
327 if (left >= table->num_chunks)
328 return table->num_chunks - 1;
333 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
335 int left = 0, right = chunk->num_elements;
337 while (left < right) {
338 int pos = (left + right) / 2;
339 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
340 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
347 g_assert (left == right);
353 mono_jit_info_table_find (MonoDomain *domain, char *addr)
355 MonoJitInfoTable *table;
358 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
360 ++mono_stats.jit_info_table_lookup_count;
362 /* First we have to get the domain's jit_info_table. This is
363 complicated by the fact that a writer might substitute a
364 new table and free the old one. What the writer guarantees
365 us is that it looks at the hazard pointers after it has
366 changed the jit_info_table pointer. So, if we guard the
367 table by a hazard pointer and make sure that the pointer is
368 still there after we've made it hazardous, we don't have to
369 worry about the writer freeing the table. */
370 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
372 chunk_pos = jit_info_table_index (table, (gint8*)addr);
373 g_assert (chunk_pos < table->num_chunks);
375 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
377 /* We now have a position that's very close to that of the
378 first element whose end address is higher than the one
379 we're looking for. If we don't have the exact position,
380 then we have a position below that one, so we'll just
381 search upward until we find our element. */
383 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
385 while (pos < chunk->num_elements) {
386 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
390 if (IS_JIT_INFO_TOMBSTONE (ji)) {
391 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
394 if ((gint8*)addr >= (gint8*)ji->code_start
395 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
396 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
397 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
401 /* If we find a non-tombstone element which is already
402 beyond what we're looking for, we have to end the
404 if ((gint8*)addr < (gint8*)ji->code_start)
410 } while (chunk_pos < table->num_chunks);
413 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
414 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
416 /* maybe it is shared code, so we also search in the root domain */
418 if (domain != mono_root_domain)
419 ji = mono_jit_info_table_find (mono_root_domain, addr);
422 /* Maybe its an AOT module */
423 MonoImage *image = mono_jit_info_find_aot_module ((guint8*)addr);
425 ji = jit_info_find_in_aot_func (domain, image, addr);
431 static G_GNUC_UNUSED void
432 jit_info_table_check (MonoJitInfoTable *table)
436 for (i = 0; i < table->num_chunks; ++i) {
437 MonoJitInfoTableChunk *chunk = table->chunks [i];
440 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
441 if (chunk->refcount > 10)
442 printf("warning: chunk refcount is %d\n", chunk->refcount);
443 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
445 for (j = 0; j < chunk->num_elements; ++j) {
446 MonoJitInfo *this = chunk->data [j];
449 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
451 if (j < chunk->num_elements - 1)
452 next = chunk->data [j + 1];
453 else if (i < table->num_chunks - 1) {
456 for (k = i + 1; k < table->num_chunks; ++k)
457 if (table->chunks [k]->num_elements > 0)
460 if (k >= table->num_chunks)
463 g_assert (table->chunks [k]->num_elements > 0);
464 next = table->chunks [k]->data [0];
468 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
473 static MonoJitInfoTable*
474 jit_info_table_realloc (MonoJitInfoTable *old)
477 int num_elements = jit_info_table_num_elements (old);
480 int new_chunk, new_element;
481 MonoJitInfoTable *new;
483 /* number of needed places for elements needed */
484 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
485 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
487 new = g_malloc (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*) * num_chunks);
488 new->domain = old->domain;
489 new->num_chunks = num_chunks;
491 for (i = 0; i < num_chunks; ++i)
492 new->chunks [i] = jit_info_table_new_chunk ();
496 for (i = 0; i < old->num_chunks; ++i) {
497 MonoJitInfoTableChunk *chunk = old->chunks [i];
498 int chunk_num_elements = chunk->num_elements;
501 for (j = 0; j < chunk_num_elements; ++j) {
502 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
503 g_assert (new_chunk < num_chunks);
504 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
505 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
506 new->chunks [new_chunk]->num_elements = new_element;
514 if (new_chunk < num_chunks) {
515 g_assert (new_chunk == num_chunks - 1);
516 new->chunks [new_chunk]->num_elements = new_element;
517 g_assert (new->chunks [new_chunk]->num_elements > 0);
520 for (i = 0; i < num_chunks; ++i) {
521 MonoJitInfoTableChunk *chunk = new->chunks [i];
522 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
524 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
531 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
533 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
534 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
536 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
538 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
539 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
541 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
542 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
544 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
545 + new1->data [new1->num_elements - 1]->code_size;
546 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
547 + new2->data [new2->num_elements - 1]->code_size;
553 static MonoJitInfoTable*
554 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
556 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
557 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
560 new_table->domain = table->domain;
561 new_table->num_chunks = table->num_chunks + 1;
564 for (i = 0; i < table->num_chunks; ++i) {
565 if (table->chunks [i] == chunk) {
566 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
569 new_table->chunks [j] = table->chunks [i];
570 ++new_table->chunks [j]->refcount;
575 g_assert (j == new_table->num_chunks);
580 static MonoJitInfoTableChunk*
581 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
583 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
587 for (i = 0; i < old->num_elements; ++i) {
588 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
589 new->data [j++] = old->data [i];
592 new->num_elements = j;
593 if (new->num_elements > 0)
594 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
596 new->last_code_end = old->last_code_end;
601 static MonoJitInfoTable*
602 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
604 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
605 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
608 new_table->domain = table->domain;
609 new_table->num_chunks = table->num_chunks;
612 for (i = 0; i < table->num_chunks; ++i) {
613 if (table->chunks [i] == chunk)
614 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
616 new_table->chunks [j] = table->chunks [i];
617 ++new_table->chunks [j]->refcount;
622 g_assert (j == new_table->num_chunks);
627 /* As we add an element to the table the case can arise that the chunk
628 * to which we need to add is already full. In that case we have to
629 * allocate a new table and do something about that chunk. We have
630 * several strategies:
632 * If the number of elements in the table is below the low watermark
633 * or above the high watermark, we reallocate the whole table.
634 * Otherwise we only concern ourselves with the overflowing chunk:
636 * If there are no tombstones in the chunk then we split the chunk in
637 * two, each half full.
639 * If the chunk does contain tombstones, we just make a new copy of
640 * the chunk without the tombstones, which will have room for at least
641 * the one element we have to add.
643 static MonoJitInfoTable*
644 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
646 int num_elements = jit_info_table_num_elements (table);
649 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
650 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
651 //printf ("reallocing table\n");
652 return jit_info_table_realloc (table);
655 /* count the number of non-tombstone elements in the chunk */
657 for (i = 0; i < chunk->num_elements; ++i) {
658 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
662 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
663 //printf ("splitting chunk\n");
664 return jit_info_table_copy_and_split_chunk (table, chunk);
667 //printf ("purifying chunk\n");
668 return jit_info_table_copy_and_purify_chunk (table, chunk);
671 /* We add elements to the table by first making space for them by
672 * shifting the elements at the back to the right, one at a time.
673 * This results in duplicate entries during the process, but during
674 * all the time the table is in a sorted state. Also, when an element
675 * is replaced by another one, the element that replaces it has an end
676 * address that is equal to or lower than that of the replaced
677 * element. That property is necessary to guarantee that when
678 * searching for an element we end up at a position not higher than
679 * the one we're looking for (i.e. we either find the element directly
680 * or we end up to the left of it).
683 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
685 MonoJitInfoTable *table;
687 MonoJitInfoTableChunk *chunk;
691 g_assert (ji->method != NULL);
693 mono_domain_lock (domain);
695 ++mono_stats.jit_info_table_insert_count;
697 table = domain->jit_info_table;
700 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
701 g_assert (chunk_pos < table->num_chunks);
702 chunk = table->chunks [chunk_pos];
704 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
705 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
707 /* Debugging code, should be removed. */
708 //jit_info_table_check (new_table);
710 domain->jit_info_table = new_table;
711 mono_memory_barrier ();
712 domain->num_jit_info_tables++;
713 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free);
719 /* Debugging code, should be removed. */
720 //jit_info_table_check (table);
722 num_elements = chunk->num_elements;
724 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
726 /* First we need to size up the chunk by one, by copying the
727 last item, or inserting the first one, if the table is
729 if (num_elements > 0)
730 chunk->data [num_elements] = chunk->data [num_elements - 1];
732 chunk->data [0] = ji;
733 mono_memory_write_barrier ();
734 chunk->num_elements = ++num_elements;
736 /* Shift the elements up one by one. */
737 for (i = num_elements - 2; i >= pos; --i) {
738 mono_memory_write_barrier ();
739 chunk->data [i + 1] = chunk->data [i];
742 /* Now we have room and can insert the new item. */
743 mono_memory_write_barrier ();
744 chunk->data [pos] = ji;
746 /* Set the high code end address chunk entry. */
747 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
748 + chunk->data [chunk->num_elements - 1]->code_size;
750 /* Debugging code, should be removed. */
751 //jit_info_table_check (table);
753 mono_domain_unlock (domain);
757 mono_jit_info_make_tombstone (MonoJitInfo *ji)
759 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
761 tombstone->code_start = ji->code_start;
762 tombstone->code_size = ji->code_size;
763 tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
769 * LOCKING: domain lock
772 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
774 if (domain->num_jit_info_tables <= 1) {
775 /* Can it actually happen that we only have one table
776 but ji is still hazardous? */
777 mono_thread_hazardous_free_or_queue (ji, g_free);
779 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
784 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
786 MonoJitInfoTable *table;
787 MonoJitInfoTableChunk *chunk;
788 gpointer start = ji->code_start;
791 mono_domain_lock (domain);
792 table = domain->jit_info_table;
794 ++mono_stats.jit_info_table_remove_count;
796 chunk_pos = jit_info_table_index (table, start);
797 g_assert (chunk_pos < table->num_chunks);
799 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
802 chunk = table->chunks [chunk_pos];
804 while (pos < chunk->num_elements) {
805 if (chunk->data [pos] == ji)
808 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
809 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
810 <= (guint8*)ji->code_start + ji->code_size);
817 } while (chunk_pos < table->num_chunks);
820 g_assert (chunk->data [pos] == ji);
822 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
824 /* Debugging code, should be removed. */
825 //jit_info_table_check (table);
827 mono_jit_info_free_or_queue (domain, ji);
829 mono_domain_unlock (domain);
832 static MonoAotModuleInfoTable*
833 mono_aot_module_info_table_new (void)
835 return g_array_new (FALSE, FALSE, sizeof (gpointer));
839 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
841 int left = 0, right = table->len;
843 while (left < right) {
844 int pos = (left + right) / 2;
845 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
846 char *start = ainfo->start;
847 char *end = ainfo->end;
851 else if (addr >= end)
861 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
863 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
866 ainfo->image = image;
867 ainfo->start = start;
870 mono_appdomains_lock ();
873 aot_modules = mono_aot_module_info_table_new ();
875 pos = aot_info_table_index (aot_modules, start);
877 g_array_insert_val (aot_modules, pos, ainfo);
879 mono_appdomains_unlock ();
883 mono_jit_info_find_aot_module (guint8* addr)
885 guint left = 0, right;
890 mono_appdomains_lock ();
892 right = aot_modules->len;
893 while (left < right) {
894 guint pos = (left + right) / 2;
895 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
897 if (addr < (guint8*)ai->start)
899 else if (addr >= (guint8*)ai->end)
902 mono_appdomains_unlock ();
907 mono_appdomains_unlock ();
913 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
915 jit_info_find_in_aot_func = func;
919 mono_jit_info_get_code_start (MonoJitInfo* ji)
921 return ji->code_start;
925 mono_jit_info_get_code_size (MonoJitInfo* ji)
927 return ji->code_size;
931 mono_jit_info_get_method (MonoJitInfo* ji)
937 jit_info_key_extract (gpointer value)
939 MonoJitInfo *info = (MonoJitInfo*)value;
945 jit_info_next_value (gpointer value)
947 MonoJitInfo *info = (MonoJitInfo*)value;
949 return (gpointer*)&info->next_jit_code_hash;
953 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
955 mono_internal_hash_table_init (jit_code_hash,
956 mono_aligned_addr_hash,
957 jit_info_key_extract,
958 jit_info_next_value);
962 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
964 if (ji->has_generic_jit_info)
965 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
971 * mono_jit_info_get_generic_sharing_context:
974 * Returns the jit info's generic sharing context, or NULL if it
977 MonoGenericSharingContext*
978 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
980 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
983 return gi->generic_sharing_context;
989 * mono_jit_info_set_generic_sharing_context:
991 * @gsctx: a generic sharing context
993 * Sets the jit info's generic sharing context. The jit info must
994 * have memory allocated for the context.
997 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
999 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
1003 gi->generic_sharing_context = gsctx;
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 guint32 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] |= 1 << (bit % 32);
1152 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1154 mono_appdomains_unlock ();
1156 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1157 domain->shadow_serial = shadow_serial;
1158 domain->domain = NULL;
1159 domain->setup = NULL;
1160 domain->friendly_name = NULL;
1161 domain->search_path = NULL;
1163 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1165 domain->mp = mono_mempool_new ();
1166 domain->code_mp = mono_code_manager_new ();
1167 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1168 domain->domain_assemblies = NULL;
1169 domain->class_vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
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);
1179 InitializeCriticalSection (&domain->lock);
1180 InitializeCriticalSection (&domain->assemblies_lock);
1181 InitializeCriticalSection (&domain->jit_code_hash_lock);
1183 domain->method_rgctx_hash = NULL;
1185 mono_appdomains_lock ();
1186 domain_id_alloc (domain);
1187 mono_appdomains_unlock ();
1189 mono_perfcounters->loader_appdomains++;
1190 mono_perfcounters->loader_total_appdomains++;
1192 mono_debug_domain_create (domain);
1194 if (create_domain_hook)
1195 create_domain_hook (domain);
1197 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1203 * mono_init_internal:
1205 * Creates the initial application domain and initializes the mono_defaults
1207 * This function is guaranteed to not run any IL code.
1208 * If exe_filename is not NULL, the method will determine the required runtime
1209 * from the exe configuration file or the version PE field.
1210 * If runtime_version is not NULL, that runtime version will be used.
1211 * Either exe_filename or runtime_version must be provided.
1213 * Returns: the initial domain.
1216 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1218 static MonoDomain *domain = NULL;
1219 MonoAssembly *ass = NULL;
1220 MonoImageOpenStatus status = MONO_IMAGE_OK;
1221 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1225 g_assert_not_reached ();
1227 #ifdef PLATFORM_WIN32
1228 /* Avoid system error message boxes. */
1229 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1231 mono_load_coree (exe_filename);
1234 mono_perfcounters_init ();
1236 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1237 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1238 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1240 mono_gc_base_init ();
1242 appdomain_thread_id = TlsAlloc ();
1244 InitializeCriticalSection (&appdomains_mutex);
1246 mono_metadata_init ();
1247 mono_images_init ();
1248 mono_assemblies_init ();
1249 mono_classes_init ();
1250 mono_loader_init ();
1251 mono_reflection_init ();
1253 /* FIXME: When should we release this memory? */
1254 MONO_GC_REGISTER_ROOT (appdomains_list);
1256 domain = mono_domain_create ();
1257 mono_root_domain = domain;
1259 SET_APPDOMAIN (domain);
1261 /* Get a list of runtimes supported by the exe */
1262 if (exe_filename != NULL) {
1264 * This function will load the exe file as a MonoImage. We need to close it, but
1265 * that would mean it would be reloaded later. So instead, we save it to
1266 * exe_image, and close it during shutdown.
1268 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1269 #ifdef PLATFORM_WIN32
1271 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1273 exe_image = mono_image_open (exe_filename, NULL);
1275 mono_fixup_exe_image (exe_image);
1277 } else if (runtime_version != NULL) {
1278 runtimes [0] = get_runtime_by_version (runtime_version);
1279 runtimes [1] = NULL;
1282 if (runtimes [0] == NULL) {
1283 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1284 runtimes [0] = default_runtime;
1285 runtimes [1] = NULL;
1286 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1287 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1290 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1291 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1292 current_runtime = runtimes [n];
1293 ass = mono_assembly_load_corlib (current_runtime, &status);
1294 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1299 /* Now that we have a runtime, set the policy for unhandled exceptions */
1300 if (mono_framework_version () < 2) {
1301 mono_runtime_unhandled_exception_policy_set (MONO_UNHANDLED_POLICY_LEGACY);
1304 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1306 case MONO_IMAGE_ERROR_ERRNO: {
1307 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1308 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1309 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1310 g_free (corlib_file);
1313 case MONO_IMAGE_IMAGE_INVALID:
1314 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1315 mono_assembly_getrootdir ());
1317 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1318 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1319 mono_assembly_getrootdir ());
1322 /* to suppress compiler warning */
1328 mono_defaults.corlib = mono_assembly_get_image (ass);
1330 mono_defaults.object_class = mono_class_from_name (
1331 mono_defaults.corlib, "System", "Object");
1332 g_assert (mono_defaults.object_class != 0);
1334 mono_defaults.void_class = mono_class_from_name (
1335 mono_defaults.corlib, "System", "Void");
1336 g_assert (mono_defaults.void_class != 0);
1338 mono_defaults.boolean_class = mono_class_from_name (
1339 mono_defaults.corlib, "System", "Boolean");
1340 g_assert (mono_defaults.boolean_class != 0);
1342 mono_defaults.byte_class = mono_class_from_name (
1343 mono_defaults.corlib, "System", "Byte");
1344 g_assert (mono_defaults.byte_class != 0);
1346 mono_defaults.sbyte_class = mono_class_from_name (
1347 mono_defaults.corlib, "System", "SByte");
1348 g_assert (mono_defaults.sbyte_class != 0);
1350 mono_defaults.int16_class = mono_class_from_name (
1351 mono_defaults.corlib, "System", "Int16");
1352 g_assert (mono_defaults.int16_class != 0);
1354 mono_defaults.uint16_class = mono_class_from_name (
1355 mono_defaults.corlib, "System", "UInt16");
1356 g_assert (mono_defaults.uint16_class != 0);
1358 mono_defaults.int32_class = mono_class_from_name (
1359 mono_defaults.corlib, "System", "Int32");
1360 g_assert (mono_defaults.int32_class != 0);
1362 mono_defaults.uint32_class = mono_class_from_name (
1363 mono_defaults.corlib, "System", "UInt32");
1364 g_assert (mono_defaults.uint32_class != 0);
1366 mono_defaults.uint_class = mono_class_from_name (
1367 mono_defaults.corlib, "System", "UIntPtr");
1368 g_assert (mono_defaults.uint_class != 0);
1370 mono_defaults.int_class = mono_class_from_name (
1371 mono_defaults.corlib, "System", "IntPtr");
1372 g_assert (mono_defaults.int_class != 0);
1374 mono_defaults.int64_class = mono_class_from_name (
1375 mono_defaults.corlib, "System", "Int64");
1376 g_assert (mono_defaults.int64_class != 0);
1378 mono_defaults.uint64_class = mono_class_from_name (
1379 mono_defaults.corlib, "System", "UInt64");
1380 g_assert (mono_defaults.uint64_class != 0);
1382 mono_defaults.single_class = mono_class_from_name (
1383 mono_defaults.corlib, "System", "Single");
1384 g_assert (mono_defaults.single_class != 0);
1386 mono_defaults.double_class = mono_class_from_name (
1387 mono_defaults.corlib, "System", "Double");
1388 g_assert (mono_defaults.double_class != 0);
1390 mono_defaults.char_class = mono_class_from_name (
1391 mono_defaults.corlib, "System", "Char");
1392 g_assert (mono_defaults.char_class != 0);
1394 mono_defaults.string_class = mono_class_from_name (
1395 mono_defaults.corlib, "System", "String");
1396 g_assert (mono_defaults.string_class != 0);
1398 mono_defaults.enum_class = mono_class_from_name (
1399 mono_defaults.corlib, "System", "Enum");
1400 g_assert (mono_defaults.enum_class != 0);
1402 mono_defaults.array_class = mono_class_from_name (
1403 mono_defaults.corlib, "System", "Array");
1404 g_assert (mono_defaults.array_class != 0);
1406 mono_defaults.delegate_class = mono_class_from_name (
1407 mono_defaults.corlib, "System", "Delegate");
1408 g_assert (mono_defaults.delegate_class != 0 );
1410 mono_defaults.multicastdelegate_class = mono_class_from_name (
1411 mono_defaults.corlib, "System", "MulticastDelegate");
1412 g_assert (mono_defaults.multicastdelegate_class != 0 );
1414 mono_defaults.asyncresult_class = mono_class_from_name (
1415 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1417 g_assert (mono_defaults.asyncresult_class != 0 );
1419 mono_defaults.waithandle_class = mono_class_from_name (
1420 mono_defaults.corlib, "System.Threading", "WaitHandle");
1421 g_assert (mono_defaults.waithandle_class != 0 );
1423 mono_defaults.typehandle_class = mono_class_from_name (
1424 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1425 g_assert (mono_defaults.typehandle_class != 0);
1427 mono_defaults.methodhandle_class = mono_class_from_name (
1428 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1429 g_assert (mono_defaults.methodhandle_class != 0);
1431 mono_defaults.fieldhandle_class = mono_class_from_name (
1432 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1433 g_assert (mono_defaults.fieldhandle_class != 0);
1435 mono_defaults.systemtype_class = mono_class_from_name (
1436 mono_defaults.corlib, "System", "Type");
1437 g_assert (mono_defaults.systemtype_class != 0);
1439 mono_defaults.monotype_class = mono_class_from_name (
1440 mono_defaults.corlib, "System", "MonoType");
1441 g_assert (mono_defaults.monotype_class != 0);
1443 mono_defaults.exception_class = mono_class_from_name (
1444 mono_defaults.corlib, "System", "Exception");
1445 g_assert (mono_defaults.exception_class != 0);
1447 mono_defaults.threadabortexception_class = mono_class_from_name (
1448 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1449 g_assert (mono_defaults.threadabortexception_class != 0);
1451 mono_defaults.thread_class = mono_class_from_name (
1452 mono_defaults.corlib, "System.Threading", "Thread");
1453 g_assert (mono_defaults.thread_class != 0);
1455 mono_defaults.appdomain_class = mono_class_from_name (
1456 mono_defaults.corlib, "System", "AppDomain");
1457 g_assert (mono_defaults.appdomain_class != 0);
1459 mono_defaults.transparent_proxy_class = mono_class_from_name (
1460 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1461 g_assert (mono_defaults.transparent_proxy_class != 0);
1463 mono_defaults.real_proxy_class = mono_class_from_name (
1464 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1465 g_assert (mono_defaults.real_proxy_class != 0);
1467 mono_defaults.mono_method_message_class = mono_class_from_name (
1468 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1469 g_assert (mono_defaults.mono_method_message_class != 0);
1471 mono_defaults.field_info_class = mono_class_from_name (
1472 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1473 g_assert (mono_defaults.field_info_class != 0);
1475 mono_defaults.method_info_class = mono_class_from_name (
1476 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1477 g_assert (mono_defaults.method_info_class != 0);
1479 mono_defaults.stringbuilder_class = mono_class_from_name (
1480 mono_defaults.corlib, "System.Text", "StringBuilder");
1481 g_assert (mono_defaults.stringbuilder_class != 0);
1483 mono_defaults.math_class = mono_class_from_name (
1484 mono_defaults.corlib, "System", "Math");
1485 g_assert (mono_defaults.math_class != 0);
1487 mono_defaults.stack_frame_class = mono_class_from_name (
1488 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1489 g_assert (mono_defaults.stack_frame_class != 0);
1491 mono_defaults.stack_trace_class = mono_class_from_name (
1492 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1493 g_assert (mono_defaults.stack_trace_class != 0);
1495 mono_defaults.marshal_class = mono_class_from_name (
1496 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1497 g_assert (mono_defaults.marshal_class != 0);
1499 mono_defaults.iserializeable_class = mono_class_from_name (
1500 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1501 g_assert (mono_defaults.iserializeable_class != 0);
1503 mono_defaults.serializationinfo_class = mono_class_from_name (
1504 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1505 g_assert (mono_defaults.serializationinfo_class != 0);
1507 mono_defaults.streamingcontext_class = mono_class_from_name (
1508 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1509 g_assert (mono_defaults.streamingcontext_class != 0);
1511 mono_defaults.typed_reference_class = mono_class_from_name (
1512 mono_defaults.corlib, "System", "TypedReference");
1513 g_assert (mono_defaults.typed_reference_class != 0);
1515 mono_defaults.argumenthandle_class = mono_class_from_name (
1516 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1517 g_assert (mono_defaults.argumenthandle_class != 0);
1519 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1520 mono_defaults.corlib, "System", "MarshalByRefObject");
1521 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1523 mono_defaults.monitor_class = mono_class_from_name (
1524 mono_defaults.corlib, "System.Threading", "Monitor");
1525 g_assert (mono_defaults.monitor_class != 0);
1527 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1528 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1529 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1531 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1532 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1534 mono_defaults.executioncontext_class = mono_class_from_name (
1535 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1537 mono_defaults.internals_visible_class = mono_class_from_name (
1538 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1541 * mscorlib needs a little help, only now it can load its friends list (after we have
1542 * loaded the InternalsVisibleToAttribute), load it now
1544 mono_assembly_load_friends (ass);
1546 mono_defaults.safehandle_class = mono_class_from_name (
1547 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1549 mono_defaults.handleref_class = mono_class_from_name (
1550 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1552 mono_defaults.attribute_class = mono_class_from_name (
1553 mono_defaults.corlib, "System", "Attribute");
1555 mono_defaults.customattribute_data_class = mono_class_from_name (
1556 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1558 /* these are initialized lazily when COM features are used */
1559 mono_defaults.variant_class = NULL;
1560 mono_defaults.com_object_class = NULL;
1561 mono_defaults.com_interop_proxy_class = NULL;
1562 mono_defaults.iunknown_class = NULL;
1563 mono_defaults.idispatch_class = NULL;
1566 * Note that mono_defaults.generic_*_class is only non-NULL if we're
1567 * using the 2.0 corlib.
1569 mono_class_init (mono_defaults.array_class);
1570 mono_defaults.generic_nullable_class = mono_class_from_name (
1571 mono_defaults.corlib, "System", "Nullable`1");
1572 mono_defaults.generic_ilist_class = mono_class_from_name (
1573 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1575 domain->friendly_name = g_path_get_basename (filename);
1577 _mono_debug_init_corlib (domain);
1585 * Creates the initial application domain and initializes the mono_defaults
1587 * This function is guaranteed to not run any IL code.
1588 * The runtime is initialized using the default runtime version.
1590 * Returns: the initial domain.
1593 mono_init (const char *domain_name)
1595 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1599 * mono_init_from_assembly:
1601 * Creates the initial application domain and initializes the mono_defaults
1603 * This function is guaranteed to not run any IL code.
1604 * The runtime is initialized using the runtime version required by the
1605 * provided executable. The version is determined by looking at the exe
1606 * configuration file and the version PE field)
1608 * Returns: the initial domain.
1611 mono_init_from_assembly (const char *domain_name, const char *filename)
1613 return mono_init_internal (domain_name, filename, NULL);
1617 * mono_init_version:
1619 * Creates the initial application domain and initializes the mono_defaults
1621 * This function is guaranteed to not run any IL code.
1622 * The runtime is initialized using the provided rutime version.
1624 * Returns: the initial domain.
1627 mono_init_version (const char *domain_name, const char *version)
1629 return mono_init_internal (domain_name, NULL, version);
1633 * mono_init_com_types:
1635 * Initializes all types needed for COM Interop in mono_defaults structure.
1638 mono_init_com_types (void)
1640 static gboolean initialized = FALSE;
1645 /* FIXME: do I need some threading protection here */
1647 g_assert (mono_defaults.corlib);
1649 mono_defaults.variant_class = mono_class_from_name (
1650 mono_defaults.corlib, "System", "Variant");
1651 g_assert (mono_defaults.variant_class != 0);
1653 mono_defaults.com_object_class = mono_class_from_name (
1654 mono_defaults.corlib, "System", "__ComObject");
1655 g_assert (mono_defaults.com_object_class != 0);
1657 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1658 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1659 g_assert (mono_defaults.com_interop_proxy_class != 0);
1661 mono_defaults.iunknown_class = mono_class_from_name (
1662 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1663 g_assert (mono_defaults.iunknown_class != 0);
1665 mono_defaults.idispatch_class = mono_class_from_name (
1666 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1667 g_assert (mono_defaults.idispatch_class != 0);
1675 * Cleans up all metadata modules.
1680 mono_close_exe_image ();
1682 mono_loader_cleanup ();
1683 mono_classes_cleanup ();
1684 mono_assemblies_cleanup ();
1685 mono_images_cleanup ();
1686 mono_debug_cleanup ();
1687 mono_metadata_cleanup ();
1689 TlsFree (appdomain_thread_id);
1690 DeleteCriticalSection (&appdomains_mutex);
1694 mono_close_exe_image (void)
1697 mono_image_close (exe_image);
1701 * mono_get_root_domain:
1703 * The root AppDomain is the initial domain created by the runtime when it is
1704 * initialized. Programs execute on this AppDomain, but can create new ones
1705 * later. Currently there is no unmanaged API to create new AppDomains, this
1706 * must be done from managed code.
1708 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1711 mono_get_root_domain (void)
1713 return mono_root_domain;
1719 * Returns: the current domain, to obtain the root domain use
1720 * mono_get_root_domain().
1725 return GET_APPDOMAIN ();
1729 * mono_domain_set_internal:
1730 * @domain: the new domain
1732 * Sets the current domain to @domain.
1735 mono_domain_set_internal (MonoDomain *domain)
1737 SET_APPDOMAIN (domain);
1738 SET_APPCONTEXT (domain->default_context);
1742 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1748 * Create a copy of the data to avoid calling the user callback
1749 * inside the lock because that could lead to deadlocks.
1750 * We can do this because this function is not perf. critical.
1752 mono_appdomains_lock ();
1753 size = appdomain_list_size;
1754 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1755 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1756 mono_appdomains_unlock ();
1758 for (i = 0; i < size; ++i) {
1760 func (copy [i], user_data);
1763 mono_gc_free_fixed (copy);
1767 * mono_domain_assembly_open:
1768 * @domain: the application domain
1769 * @name: file name of the assembly
1771 * fixme: maybe we should integrate this with mono_assembly_open ??
1774 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1779 mono_domain_assemblies_lock (domain);
1780 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1782 if (strcmp (name, ass->aname.name) == 0) {
1783 mono_domain_assemblies_unlock (domain);
1787 mono_domain_assemblies_unlock (domain);
1789 if (!(ass = mono_assembly_open (name, NULL)))
1796 mono_domain_free (MonoDomain *domain, gboolean force)
1798 int code_size, code_alloc;
1800 if ((domain == mono_root_domain) && !force) {
1801 g_warning ("cant unload root domain");
1805 if (mono_dont_free_domains)
1808 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1810 if (free_domain_hook)
1811 free_domain_hook (domain);
1813 mono_debug_domain_unload (domain);
1815 mono_appdomains_lock ();
1816 appdomains_list [domain->domain_id] = NULL;
1817 mono_appdomains_unlock ();
1819 /* FIXME: free delegate_hash_table when it's used */
1820 if (domain->search_path) {
1821 g_strfreev (domain->search_path);
1822 domain->search_path = NULL;
1824 domain->create_proxy_for_type_method = NULL;
1825 domain->private_invoke_method = NULL;
1826 domain->default_context = NULL;
1827 domain->out_of_memory_ex = NULL;
1828 domain->null_reference_ex = NULL;
1829 domain->stack_overflow_ex = NULL;
1830 domain->entry_assembly = NULL;
1831 /* must do this early as it accesses fields and types */
1832 if (domain->special_static_fields) {
1833 mono_alloc_special_static_data_free (domain->special_static_fields);
1834 g_hash_table_destroy (domain->special_static_fields);
1835 domain->special_static_fields = NULL;
1837 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1838 MonoAssembly *ass = tmp->data;
1839 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s %p, assembly %s %p, refcount=%d\n", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count);
1840 mono_assembly_close (ass);
1842 g_slist_free (domain->domain_assemblies);
1843 domain->domain_assemblies = NULL;
1845 g_free (domain->friendly_name);
1846 domain->friendly_name = NULL;
1847 mono_g_hash_table_destroy (domain->env);
1849 g_hash_table_destroy (domain->class_vtable_hash);
1850 domain->class_vtable_hash = NULL;
1851 g_hash_table_destroy (domain->proxy_vtable_hash);
1852 domain->proxy_vtable_hash = NULL;
1853 if (domain->static_data_array) {
1854 mono_gc_free_fixed (domain->static_data_array);
1855 domain->static_data_array = NULL;
1857 mono_internal_hash_table_destroy (&domain->jit_code_hash);
1858 mono_g_hash_table_destroy (domain->ldstr_table);
1859 domain->ldstr_table = NULL;
1862 * There might still be jit info tables of this domain which
1863 * are not freed. Since the domain cannot be in use anymore,
1864 * this will free them.
1866 mono_thread_hazardous_try_free_all ();
1867 g_assert (domain->num_jit_info_tables == 1);
1868 jit_info_table_free (domain->jit_info_table);
1869 domain->jit_info_table = NULL;
1870 g_assert (!domain->jit_info_free_queue);
1872 /* collect statistics */
1873 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
1874 total_domain_code_alloc += code_alloc;
1875 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
1876 max_domain_code_size = MAX (max_domain_code_size, code_size);
1878 #ifdef DEBUG_DOMAIN_UNLOAD
1879 mono_mempool_invalidate (domain->mp);
1880 mono_code_manager_invalidate (domain->code_mp);
1882 mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
1883 mono_mempool_destroy (domain->mp);
1885 mono_code_manager_destroy (domain->code_mp);
1886 domain->code_mp = NULL;
1888 if (domain->type_hash) {
1889 mono_g_hash_table_destroy (domain->type_hash);
1890 domain->type_hash = NULL;
1892 if (domain->refobject_hash) {
1893 mono_g_hash_table_destroy (domain->refobject_hash);
1894 domain->refobject_hash = NULL;
1896 if (domain->type_init_exception_hash) {
1897 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1898 domain->type_init_exception_hash = NULL;
1900 g_hash_table_destroy (domain->finalizable_objects_hash);
1901 domain->finalizable_objects_hash = NULL;
1902 if (domain->method_rgctx_hash) {
1903 g_hash_table_destroy (domain->method_rgctx_hash);
1904 domain->method_rgctx_hash = NULL;
1906 if (domain->generic_virtual_cases) {
1907 g_hash_table_destroy (domain->generic_virtual_cases);
1908 domain->generic_virtual_cases = NULL;
1911 DeleteCriticalSection (&domain->assemblies_lock);
1912 DeleteCriticalSection (&domain->jit_code_hash_lock);
1913 DeleteCriticalSection (&domain->lock);
1914 domain->setup = NULL;
1916 /* FIXME: anything else required ? */
1918 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
1920 mono_gc_free_fixed (domain);
1922 mono_perfcounters->loader_appdomains--;
1924 if ((domain == mono_root_domain))
1925 mono_root_domain = NULL;
1929 * mono_domain_get_id:
1932 * Returns: the a domain for a specific domain id.
1935 mono_domain_get_by_id (gint32 domainid)
1937 MonoDomain * domain;
1939 mono_appdomains_lock ();
1940 if (domainid < appdomain_list_size)
1941 domain = appdomains_list [domainid];
1944 mono_appdomains_unlock ();
1950 mono_domain_get_id (MonoDomain *domain)
1952 return domain->domain_id;
1956 mono_domain_alloc (MonoDomain *domain, guint size)
1958 mono_perfcounters->loader_bytes += size;
1959 return mono_mempool_alloc (domain->mp, size);
1963 mono_domain_alloc0 (MonoDomain *domain, guint size)
1965 mono_perfcounters->loader_bytes += size;
1966 return mono_mempool_alloc0 (domain->mp, size);
1970 mono_context_set (MonoAppContext * new_context)
1972 SET_APPCONTEXT (new_context);
1976 mono_context_get (void)
1978 return GET_APPCONTEXT ();
1981 /* LOCKING: the caller holds the lock for this domain */
1983 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
1985 /* The first entry in the array is the index of the next free slot
1986 * and the total size of the array
1989 if (domain->static_data_array) {
1990 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
1991 next = GPOINTER_TO_INT (domain->static_data_array [0]);
1993 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), NULL);
1994 memcpy (new_array, domain->static_data_array, sizeof (gpointer) * size);
1996 new_array [1] = GINT_TO_POINTER (size);
1997 mono_gc_free_fixed (domain->static_data_array);
1998 domain->static_data_array = new_array;
2002 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, NULL);
2004 new_array [0] = GINT_TO_POINTER (next);
2005 new_array [1] = GINT_TO_POINTER (size);
2006 domain->static_data_array = new_array;
2008 domain->static_data_array [next++] = data;
2009 domain->static_data_array [0] = GINT_TO_POINTER (next);
2013 mono_get_corlib (void)
2015 return mono_defaults.corlib;
2019 mono_get_object_class (void)
2021 return mono_defaults.object_class;
2025 mono_get_byte_class (void)
2027 return mono_defaults.byte_class;
2031 mono_get_void_class (void)
2033 return mono_defaults.void_class;
2037 mono_get_boolean_class (void)
2039 return mono_defaults.boolean_class;
2043 mono_get_sbyte_class (void)
2045 return mono_defaults.sbyte_class;
2049 mono_get_int16_class (void)
2051 return mono_defaults.int16_class;
2055 mono_get_uint16_class (void)
2057 return mono_defaults.uint16_class;
2061 mono_get_int32_class (void)
2063 return mono_defaults.int32_class;
2067 mono_get_uint32_class (void)
2069 return mono_defaults.uint32_class;
2073 mono_get_intptr_class (void)
2075 return mono_defaults.int_class;
2079 mono_get_uintptr_class (void)
2081 return mono_defaults.uint_class;
2085 mono_get_int64_class (void)
2087 return mono_defaults.int64_class;
2091 mono_get_uint64_class (void)
2093 return mono_defaults.uint64_class;
2097 mono_get_single_class (void)
2099 return mono_defaults.single_class;
2103 mono_get_double_class (void)
2105 return mono_defaults.double_class;
2109 mono_get_char_class (void)
2111 return mono_defaults.char_class;
2115 mono_get_string_class (void)
2117 return mono_defaults.string_class;
2121 mono_get_enum_class (void)
2123 return mono_defaults.enum_class;
2127 mono_get_array_class (void)
2129 return mono_defaults.array_class;
2133 mono_get_thread_class (void)
2135 return mono_defaults.thread_class;
2139 mono_get_exception_class (void)
2141 return mono_defaults.exception_class;
2145 static char* get_attribute_value (const gchar **attribute_names,
2146 const gchar **attribute_values,
2147 const char *att_name)
2150 for (n=0; attribute_names[n] != NULL; n++) {
2151 if (strcmp (attribute_names[n], att_name) == 0)
2152 return g_strdup (attribute_values[n]);
2157 static void start_element (GMarkupParseContext *context,
2158 const gchar *element_name,
2159 const gchar **attribute_names,
2160 const gchar **attribute_values,
2164 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2166 if (strcmp (element_name, "configuration") == 0) {
2167 app_config->configuration_count++;
2170 if (strcmp (element_name, "startup") == 0) {
2171 app_config->startup_count++;
2175 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2178 if (strcmp (element_name, "requiredRuntime") == 0) {
2179 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2180 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2181 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2182 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2186 static void end_element (GMarkupParseContext *context,
2187 const gchar *element_name,
2191 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2193 if (strcmp (element_name, "configuration") == 0) {
2194 app_config->configuration_count--;
2195 } else if (strcmp (element_name, "startup") == 0) {
2196 app_config->startup_count--;
2200 static const GMarkupParser
2209 static AppConfigInfo *
2210 app_config_parse (const char *exe_filename)
2212 AppConfigInfo *app_config;
2213 GMarkupParseContext *context;
2217 const char *bundled_config;
2218 char *config_filename;
2220 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2222 if (bundled_config) {
2223 text = g_strdup (bundled_config);
2224 len = strlen (text);
2226 config_filename = g_strconcat (exe_filename, ".config", NULL);
2228 if (stat (config_filename, &buf) != 0) {
2229 g_free (config_filename);
2233 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2234 g_free (config_filename);
2237 g_free (config_filename);
2240 app_config = g_new0 (AppConfigInfo, 1);
2242 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2243 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2244 g_markup_parse_context_end_parse (context, NULL);
2246 g_markup_parse_context_free (context);
2252 app_config_free (AppConfigInfo* app_config)
2255 GSList *list = app_config->supported_runtimes;
2256 while (list != NULL) {
2257 rt = (char*)list->data;
2259 list = g_slist_next (list);
2261 g_slist_free (app_config->supported_runtimes);
2262 g_free (app_config->required_runtime);
2263 g_free (app_config);
2267 static const MonoRuntimeInfo*
2268 get_runtime_by_version (const char *version)
2271 int max = G_N_ELEMENTS (supported_runtimes);
2273 for (n=0; n<max; n++) {
2274 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2275 return &supported_runtimes[n];
2281 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2283 AppConfigInfo* app_config;
2285 const MonoRuntimeInfo* runtime = NULL;
2286 MonoImage *image = NULL;
2288 app_config = app_config_parse (exe_file);
2290 if (app_config != NULL) {
2291 /* Check supportedRuntime elements, if none is supported, fail.
2292 * If there are no such elements, look for a requiredRuntime element.
2294 if (app_config->supported_runtimes != NULL) {
2296 GSList *list = app_config->supported_runtimes;
2297 while (list != NULL) {
2298 version = (char*) list->data;
2299 runtime = get_runtime_by_version (version);
2300 if (runtime != NULL)
2301 runtimes [n++] = runtime;
2302 list = g_slist_next (list);
2304 runtimes [n] = NULL;
2305 app_config_free (app_config);
2309 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2310 if (app_config->required_runtime != NULL) {
2311 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2312 runtimes [1] = NULL;
2313 app_config_free (app_config);
2316 app_config_free (app_config);
2319 /* Look for a runtime with the exact version */
2320 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2323 image = mono_image_open (exe_file, NULL);
2325 if (image == NULL) {
2326 /* The image is wrong or the file was not found. In this case return
2327 * a default runtime and leave to the initialization method the work of
2328 * reporting the error.
2330 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2331 runtimes [1] = NULL;
2337 runtimes [0] = get_runtime_by_version (image->version);
2338 runtimes [1] = NULL;
2343 * mono_get_runtime_info:
2345 * Returns: the version of the current runtime instance.
2347 const MonoRuntimeInfo*
2348 mono_get_runtime_info (void)
2350 return current_runtime;
2354 mono_debugger_check_runtime_version (const char *filename)
2356 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2357 const MonoRuntimeInfo *rinfo;
2360 get_runtimes_from_exe (filename, &image, runtimes);
2361 rinfo = runtimes [0];
2364 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2366 if (rinfo != current_runtime)
2367 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2368 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2369 filename, rinfo->runtime_version);
2375 * mono_framework_version:
2377 * Return the major version of the framework curently executing.
2380 mono_framework_version (void)
2382 return current_runtime->framework_version [0] - '0';