2 * domain.c: MonoDomain functions
5 * Dietmar Maurer (dietmar@ximian.com)
8 * (C) 2001 Ximian, Inc.
16 #include <mono/metadata/gc-internal.h>
18 #include <mono/utils/mono-compiler.h>
19 #include <mono/utils/mono-logger.h>
20 #include <mono/utils/mono-membar.h>
21 #include <mono/utils/mono-counters.h>
22 #include <mono/metadata/object.h>
23 #include <mono/metadata/object-internals.h>
24 #include <mono/metadata/domain-internals.h>
25 #include <mono/metadata/class-internals.h>
26 #include <mono/metadata/assembly.h>
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/rawbuffer.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 /* This is intentionally not in the header file, so people don't misuse it. */
126 extern void _mono_debug_init_corlib (MonoDomain *domain);
129 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
131 static const MonoRuntimeInfo*
132 get_runtime_by_version (const char *version);
135 mono_jit_info_find_aot_module (guint8* addr);
138 mono_domain_get_tls_key (void)
140 return appdomain_thread_id;
144 mono_domain_get_tls_offset (void)
147 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
148 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
153 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
154 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
155 #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)
157 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
158 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
160 #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
161 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
163 #define JIT_INFO_TABLE_HAZARD_INDEX 0
164 #define JIT_INFO_HAZARD_INDEX 1
167 jit_info_table_num_elements (MonoJitInfoTable *table)
170 int num_elements = 0;
172 for (i = 0; i < table->num_chunks; ++i) {
173 MonoJitInfoTableChunk *chunk = table->chunks [i];
174 int chunk_num_elements = chunk->num_elements;
177 for (j = 0; j < chunk_num_elements; ++j) {
178 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
186 static MonoJitInfoTableChunk*
187 jit_info_table_new_chunk (void)
189 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
195 static MonoJitInfoTable *
196 jit_info_table_new (MonoDomain *domain)
198 MonoJitInfoTable *table = g_malloc0 (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*));
200 table->domain = domain;
201 table->num_chunks = 1;
202 table->chunks [0] = jit_info_table_new_chunk ();
208 jit_info_table_free (MonoJitInfoTable *table)
211 int num_chunks = table->num_chunks;
212 MonoDomain *domain = table->domain;
214 mono_domain_lock (domain);
216 table->domain->num_jit_info_tables--;
217 if (table->domain->num_jit_info_tables <= 1) {
220 for (list = table->domain->jit_info_free_queue; list; list = list->next)
223 g_slist_free (table->domain->jit_info_free_queue);
224 table->domain->jit_info_free_queue = NULL;
227 /* At this point we assume that there are no other threads
228 still accessing the table, so we don't have to worry about
229 hazardous pointers. */
231 for (i = 0; i < num_chunks; ++i) {
232 MonoJitInfoTableChunk *chunk = table->chunks [i];
236 if (--chunk->refcount > 0)
239 num_elements = chunk->num_elements;
240 for (j = 0; j < num_elements; ++j) {
241 MonoJitInfo *ji = chunk->data [j];
243 if (IS_JIT_INFO_TOMBSTONE (ji))
250 mono_domain_unlock (domain);
255 /* Can be called with hp==NULL, in which case it acts as an ordinary
256 pointer fetch. It's used that way indirectly from
257 mono_jit_info_table_add(), which doesn't have to care about hazards
258 because it holds the respective domain lock. */
260 get_hazardous_pointer (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index)
265 /* Get the pointer */
267 /* If we don't have hazard pointers just return the
271 /* Make it hazardous */
272 mono_hazard_pointer_set (hp, hazard_index, p);
273 /* Check that it's still the same. If not, try
276 mono_hazard_pointer_clear (hp, hazard_index);
285 /* The jit_info_table is sorted in ascending order by the end
286 * addresses of the compiled methods. The reason why we have to do
287 * this is that once we introduce tombstones, it becomes possible for
288 * code ranges to overlap, and if we sort by code start and insert at
289 * the back of the table, we cannot guarantee that we won't overlook
292 * There are actually two possible ways to do the sorting and
293 * inserting which work with our lock-free mechanism:
295 * 1. Sort by start address and insert at the front. When looking for
296 * an entry, find the last one with a start address lower than the one
297 * you're looking for, then work your way to the front of the table.
299 * 2. Sort by end address and insert at the back. When looking for an
300 * entry, find the first one with an end address higher than the one
301 * you're looking for, then work your way to the end of the table.
303 * We chose the latter out of convenience.
306 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
308 int left = 0, right = table->num_chunks;
310 g_assert (left < right);
313 int pos = (left + right) / 2;
314 MonoJitInfoTableChunk *chunk = table->chunks [pos];
316 if (addr < chunk->last_code_end)
320 } while (left < right);
321 g_assert (left == right);
323 if (left >= table->num_chunks)
324 return table->num_chunks - 1;
329 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
331 int left = 0, right = chunk->num_elements;
333 while (left < right) {
334 int pos = (left + right) / 2;
335 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
336 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
343 g_assert (left == right);
349 mono_jit_info_table_find (MonoDomain *domain, char *addr)
351 MonoJitInfoTable *table;
354 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
356 ++mono_stats.jit_info_table_lookup_count;
358 /* First we have to get the domain's jit_info_table. This is
359 complicated by the fact that a writer might substitute a
360 new table and free the old one. What the writer guarantees
361 us is that it looks at the hazard pointers after it has
362 changed the jit_info_table pointer. So, if we guard the
363 table by a hazard pointer and make sure that the pointer is
364 still there after we've made it hazardous, we don't have to
365 worry about the writer freeing the table. */
366 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
368 chunk_pos = jit_info_table_index (table, (gint8*)addr);
369 g_assert (chunk_pos < table->num_chunks);
371 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
373 /* We now have a position that's very close to that of the
374 first element whose end address is higher than the one
375 we're looking for. If we don't have the exact position,
376 then we have a position below that one, so we'll just
377 search upward until we find our element. */
379 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
381 while (pos < chunk->num_elements) {
382 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
386 if (IS_JIT_INFO_TOMBSTONE (ji)) {
387 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
390 if ((gint8*)addr >= (gint8*)ji->code_start
391 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
392 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
393 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
397 /* If we find a non-tombstone element which is already
398 beyond what we're looking for, we have to end the
400 if ((gint8*)addr < (gint8*)ji->code_start)
406 } while (chunk_pos < table->num_chunks);
409 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
410 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
412 /* maybe it is shared code, so we also search in the root domain */
414 if (domain != mono_root_domain)
415 ji = mono_jit_info_table_find (mono_root_domain, addr);
418 /* Maybe its an AOT module */
419 MonoImage *image = mono_jit_info_find_aot_module ((guint8*)addr);
421 ji = jit_info_find_in_aot_func (domain, image, addr);
427 static G_GNUC_UNUSED void
428 jit_info_table_check (MonoJitInfoTable *table)
432 for (i = 0; i < table->num_chunks; ++i) {
433 MonoJitInfoTableChunk *chunk = table->chunks [i];
436 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
437 if (chunk->refcount > 10)
438 printf("warning: chunk refcount is %d\n", chunk->refcount);
439 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
441 for (j = 0; j < chunk->num_elements; ++j) {
442 MonoJitInfo *this = chunk->data [j];
445 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
447 if (j < chunk->num_elements - 1)
448 next = chunk->data [j + 1];
449 else if (i < table->num_chunks - 1) {
452 for (k = i + 1; k < table->num_chunks; ++k)
453 if (table->chunks [k]->num_elements > 0)
456 if (k >= table->num_chunks)
459 g_assert (table->chunks [k]->num_elements > 0);
460 next = table->chunks [k]->data [0];
464 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
469 static MonoJitInfoTable*
470 jit_info_table_realloc (MonoJitInfoTable *old)
473 int num_elements = jit_info_table_num_elements (old);
476 int new_chunk, new_element;
477 MonoJitInfoTable *new;
479 /* number of needed places for elements needed */
480 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
481 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
483 new = g_malloc (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*) * num_chunks);
484 new->domain = old->domain;
485 new->num_chunks = num_chunks;
487 for (i = 0; i < num_chunks; ++i)
488 new->chunks [i] = jit_info_table_new_chunk ();
492 for (i = 0; i < old->num_chunks; ++i) {
493 MonoJitInfoTableChunk *chunk = old->chunks [i];
494 int chunk_num_elements = chunk->num_elements;
497 for (j = 0; j < chunk_num_elements; ++j) {
498 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
499 g_assert (new_chunk < num_chunks);
500 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
501 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
502 new->chunks [new_chunk]->num_elements = new_element;
510 if (new_chunk < num_chunks) {
511 g_assert (new_chunk == num_chunks - 1);
512 new->chunks [new_chunk]->num_elements = new_element;
513 g_assert (new->chunks [new_chunk]->num_elements > 0);
516 for (i = 0; i < num_chunks; ++i) {
517 MonoJitInfoTableChunk *chunk = new->chunks [i];
518 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
520 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
527 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
529 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
530 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
532 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
534 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
535 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
537 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
538 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
540 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
541 + new1->data [new1->num_elements - 1]->code_size;
542 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
543 + new2->data [new2->num_elements - 1]->code_size;
549 static MonoJitInfoTable*
550 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
552 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
553 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
556 new_table->domain = table->domain;
557 new_table->num_chunks = table->num_chunks + 1;
560 for (i = 0; i < table->num_chunks; ++i) {
561 if (table->chunks [i] == chunk) {
562 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
565 new_table->chunks [j] = table->chunks [i];
566 ++new_table->chunks [j]->refcount;
571 g_assert (j == new_table->num_chunks);
576 static MonoJitInfoTableChunk*
577 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
579 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
583 for (i = 0; i < old->num_elements; ++i) {
584 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
585 new->data [j++] = old->data [i];
588 new->num_elements = j;
589 if (new->num_elements > 0)
590 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
592 new->last_code_end = old->last_code_end;
597 static MonoJitInfoTable*
598 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
600 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
601 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
604 new_table->domain = table->domain;
605 new_table->num_chunks = table->num_chunks;
608 for (i = 0; i < table->num_chunks; ++i) {
609 if (table->chunks [i] == chunk)
610 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
612 new_table->chunks [j] = table->chunks [i];
613 ++new_table->chunks [j]->refcount;
618 g_assert (j == new_table->num_chunks);
623 /* As we add an element to the table the case can arise that the chunk
624 * to which we need to add is already full. In that case we have to
625 * allocate a new table and do something about that chunk. We have
626 * several strategies:
628 * If the number of elements in the table is below the low watermark
629 * or above the high watermark, we reallocate the whole table.
630 * Otherwise we only concern ourselves with the overflowing chunk:
632 * If there are no tombstones in the chunk then we split the chunk in
633 * two, each half full.
635 * If the chunk does contain tombstones, we just make a new copy of
636 * the chunk without the tombstones, which will have room for at least
637 * the one element we have to add.
639 static MonoJitInfoTable*
640 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
642 int num_elements = jit_info_table_num_elements (table);
645 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
646 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
647 //printf ("reallocing table\n");
648 return jit_info_table_realloc (table);
651 /* count the number of non-tombstone elements in the chunk */
653 for (i = 0; i < chunk->num_elements; ++i) {
654 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
658 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
659 //printf ("splitting chunk\n");
660 return jit_info_table_copy_and_split_chunk (table, chunk);
663 //printf ("purifying chunk\n");
664 return jit_info_table_copy_and_purify_chunk (table, chunk);
667 /* We add elements to the table by first making space for them by
668 * shifting the elements at the back to the right, one at a time.
669 * This results in duplicate entries during the process, but during
670 * all the time the table is in a sorted state. Also, when an element
671 * is replaced by another one, the element that replaces it has an end
672 * address that is equal to or lower than that of the replaced
673 * element. That property is necessary to guarantee that when
674 * searching for an element we end up at a position not higher than
675 * the one we're looking for (i.e. we either find the element directly
676 * or we end up to the left of it).
679 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
681 MonoJitInfoTable *table;
683 MonoJitInfoTableChunk *chunk;
687 g_assert (ji->method != NULL);
689 mono_domain_lock (domain);
691 ++mono_stats.jit_info_table_insert_count;
693 table = domain->jit_info_table;
696 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
697 g_assert (chunk_pos < table->num_chunks);
698 chunk = table->chunks [chunk_pos];
700 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
701 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
703 /* Debugging code, should be removed. */
704 //jit_info_table_check (new_table);
706 domain->jit_info_table = new_table;
707 mono_memory_barrier ();
708 domain->num_jit_info_tables++;
709 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free);
715 /* Debugging code, should be removed. */
716 //jit_info_table_check (table);
718 num_elements = chunk->num_elements;
720 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
722 /* First we need to size up the chunk by one, by copying the
723 last item, or inserting the first one, if the table is
725 if (num_elements > 0)
726 chunk->data [num_elements] = chunk->data [num_elements - 1];
728 chunk->data [0] = ji;
729 mono_memory_write_barrier ();
730 chunk->num_elements = ++num_elements;
732 /* Shift the elements up one by one. */
733 for (i = num_elements - 2; i >= pos; --i) {
734 mono_memory_write_barrier ();
735 chunk->data [i + 1] = chunk->data [i];
738 /* Now we have room and can insert the new item. */
739 mono_memory_write_barrier ();
740 chunk->data [pos] = ji;
742 /* Set the high code end address chunk entry. */
743 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
744 + chunk->data [chunk->num_elements - 1]->code_size;
746 /* Debugging code, should be removed. */
747 //jit_info_table_check (table);
749 mono_domain_unlock (domain);
753 mono_jit_info_make_tombstone (MonoJitInfo *ji)
755 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
757 tombstone->code_start = ji->code_start;
758 tombstone->code_size = ji->code_size;
759 tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
765 * LOCKING: domain lock
768 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
770 if (domain->num_jit_info_tables <= 1) {
771 /* Can it actually happen that we only have one table
772 but ji is still hazardous? */
773 mono_thread_hazardous_free_or_queue (ji, g_free);
775 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
780 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
782 MonoJitInfoTable *table;
783 MonoJitInfoTableChunk *chunk;
784 gpointer start = ji->code_start;
787 mono_domain_lock (domain);
788 table = domain->jit_info_table;
790 ++mono_stats.jit_info_table_remove_count;
792 chunk_pos = jit_info_table_index (table, start);
793 g_assert (chunk_pos < table->num_chunks);
795 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
798 chunk = table->chunks [chunk_pos];
800 while (pos < chunk->num_elements) {
801 if (chunk->data [pos] == ji)
804 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
805 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
806 <= (guint8*)ji->code_start + ji->code_size);
813 } while (chunk_pos < table->num_chunks);
816 g_assert (chunk->data [pos] == ji);
818 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
820 /* Debugging code, should be removed. */
821 //jit_info_table_check (table);
823 mono_jit_info_free_or_queue (domain, ji);
825 mono_domain_unlock (domain);
828 static MonoAotModuleInfoTable*
829 mono_aot_module_info_table_new (void)
831 return g_array_new (FALSE, FALSE, sizeof (gpointer));
835 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
837 int left = 0, right = table->len;
839 while (left < right) {
840 int pos = (left + right) / 2;
841 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
842 char *start = ainfo->start;
843 char *end = ainfo->end;
847 else if (addr >= end)
857 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
859 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
862 ainfo->image = image;
863 ainfo->start = start;
866 mono_appdomains_lock ();
869 aot_modules = mono_aot_module_info_table_new ();
871 pos = aot_info_table_index (aot_modules, start);
873 g_array_insert_val (aot_modules, pos, ainfo);
875 mono_appdomains_unlock ();
879 mono_jit_info_find_aot_module (guint8* addr)
881 guint left = 0, right;
886 mono_appdomains_lock ();
888 right = aot_modules->len;
889 while (left < right) {
890 guint pos = (left + right) / 2;
891 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
893 if (addr < (guint8*)ai->start)
895 else if (addr >= (guint8*)ai->end)
898 mono_appdomains_unlock ();
903 mono_appdomains_unlock ();
909 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
911 jit_info_find_in_aot_func = func;
915 mono_jit_info_get_code_start (MonoJitInfo* ji)
917 return ji->code_start;
921 mono_jit_info_get_code_size (MonoJitInfo* ji)
923 return ji->code_size;
927 mono_jit_info_get_method (MonoJitInfo* ji)
933 jit_info_key_extract (gpointer value)
935 MonoJitInfo *info = (MonoJitInfo*)value;
941 jit_info_next_value (gpointer value)
943 MonoJitInfo *info = (MonoJitInfo*)value;
945 return (gpointer*)&info->next_jit_code_hash;
949 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
951 mono_internal_hash_table_init (jit_code_hash,
952 mono_aligned_addr_hash,
953 jit_info_key_extract,
954 jit_info_next_value);
958 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
960 if (ji->has_generic_jit_info)
961 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
967 * mono_jit_info_get_generic_sharing_context:
970 * Returns the jit info's generic sharing context, or NULL if it
973 MonoGenericSharingContext*
974 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
976 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
979 return gi->generic_sharing_context;
985 * mono_jit_info_set_generic_sharing_context:
987 * @gsctx: a generic sharing context
989 * Sets the jit info's generic sharing context. The jit info must
990 * have memory allocated for the context.
993 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
995 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
999 gi->generic_sharing_context = gsctx;
1003 * mono_string_equal:
1004 * @s1: First string to compare
1005 * @s2: Second string to compare
1007 * Returns FALSE if the strings differ.
1010 mono_string_equal (MonoString *s1, MonoString *s2)
1012 int l1 = mono_string_length (s1);
1013 int l2 = mono_string_length (s2);
1020 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
1025 * @s: the string to hash
1027 * Returns the hash for the string.
1030 mono_string_hash (MonoString *s)
1032 const guint16 *p = mono_string_chars (s);
1033 int i, len = mono_string_length (s);
1036 for (i = 0; i < len; i++) {
1037 h = (h << 5) - h + *p;
1045 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1047 int len = GPOINTER_TO_INT (s1 [0]);
1048 if (len != GPOINTER_TO_INT (s2 [0]))
1051 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1055 mono_ptrarray_hash (gpointer *s)
1058 int len = GPOINTER_TO_INT (s [0]);
1061 for (i = 1; i < len; i++)
1062 hash += GPOINTER_TO_UINT (s [i]);
1068 * Allocate an id for domain and set domain->domain_id.
1069 * LOCKING: must be called while holding appdomains_mutex.
1070 * We try to assign low numbers to the domain, so it can be used
1071 * as an index in data tables to lookup domain-specific info
1072 * with minimal memory overhead. We also try not to reuse the
1073 * same id too quickly (to help debugging).
1076 domain_id_alloc (MonoDomain *domain)
1079 if (!appdomains_list) {
1080 appdomain_list_size = 2;
1081 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1083 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1084 if (!appdomains_list [i]) {
1090 for (i = 0; i < appdomain_next; ++i) {
1091 if (!appdomains_list [i]) {
1098 MonoDomain **new_list;
1099 int new_size = appdomain_list_size * 2;
1100 if (new_size >= (1 << 16))
1101 g_assert_not_reached ();
1102 id = appdomain_list_size;
1103 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1104 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1105 mono_gc_free_fixed (appdomains_list);
1106 appdomains_list = new_list;
1107 appdomain_list_size = new_size;
1109 domain->domain_id = id;
1110 appdomains_list [id] = domain;
1112 if (appdomain_next > appdomain_list_size)
1117 static guint32 domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1118 static gpointer domain_gc_desc = NULL;
1119 static guint32 domain_shadow_serial = 0L;
1122 mono_domain_create (void)
1125 guint32 shadow_serial;
1127 mono_appdomains_lock ();
1128 shadow_serial = domain_shadow_serial++;
1130 if (!domain_gc_desc) {
1131 unsigned int i, bit = 0;
1132 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1133 bit = i / sizeof (gpointer);
1134 domain_gc_bitmap [bit / 32] |= 1 << (bit % 32);
1136 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1138 mono_appdomains_unlock ();
1140 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1141 domain->shadow_serial = shadow_serial;
1142 domain->domain = NULL;
1143 domain->setup = NULL;
1144 domain->friendly_name = NULL;
1145 domain->search_path = NULL;
1147 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1149 domain->mp = mono_mempool_new ();
1150 domain->code_mp = mono_code_manager_new ();
1151 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1152 domain->domain_assemblies = NULL;
1153 domain->class_vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1154 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1155 domain->static_data_array = NULL;
1156 mono_jit_code_hash_init (&domain->jit_code_hash);
1157 domain->ldstr_table = mono_g_hash_table_new ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal);
1158 domain->num_jit_info_tables = 1;
1159 domain->jit_info_table = jit_info_table_new (domain);
1160 domain->jit_info_free_queue = NULL;
1161 domain->class_init_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1162 domain->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1163 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1164 domain->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1165 domain->delegate_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1167 InitializeCriticalSection (&domain->lock);
1168 InitializeCriticalSection (&domain->assemblies_lock);
1169 InitializeCriticalSection (&domain->jit_code_hash_lock);
1171 domain->shared_generics_hash = NULL;
1172 domain->method_rgctx_hash = NULL;
1173 domain->method_code_hash = NULL;
1175 mono_appdomains_lock ();
1176 domain_id_alloc (domain);
1177 mono_appdomains_unlock ();
1179 mono_debug_domain_create (domain);
1181 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1187 * mono_init_internal:
1189 * Creates the initial application domain and initializes the mono_defaults
1191 * This function is guaranteed to not run any IL code.
1192 * If exe_filename is not NULL, the method will determine the required runtime
1193 * from the exe configuration file or the version PE field.
1194 * If runtime_version is not NULL, that runtime version will be used.
1195 * Either exe_filename or runtime_version must be provided.
1197 * Returns: the initial domain.
1200 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1202 static MonoDomain *domain = NULL;
1203 MonoAssembly *ass = NULL;
1204 MonoImageOpenStatus status = MONO_IMAGE_OK;
1205 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1209 g_assert_not_reached ();
1211 #ifdef PLATFORM_WIN32
1212 /* Avoid system error message boxes. */
1213 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1215 mono_load_coree (exe_filename);
1218 mono_perfcounters_init ();
1220 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1221 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1222 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1224 mono_gc_base_init ();
1226 appdomain_thread_id = TlsAlloc ();
1228 InitializeCriticalSection (&appdomains_mutex);
1230 mono_metadata_init ();
1231 mono_raw_buffer_init ();
1232 mono_images_init ();
1233 mono_assemblies_init ();
1234 mono_classes_init ();
1235 mono_loader_init ();
1236 mono_reflection_init ();
1238 /* FIXME: When should we release this memory? */
1239 MONO_GC_REGISTER_ROOT (appdomains_list);
1241 domain = mono_domain_create ();
1242 mono_root_domain = domain;
1244 SET_APPDOMAIN (domain);
1246 /* Get a list of runtimes supported by the exe */
1247 if (exe_filename != NULL) {
1249 * This function will load the exe file as a MonoImage. We need to close it, but
1250 * that would mean it would be reloaded later. So instead, we save it to
1251 * exe_image, and close it during shutdown.
1253 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1254 #ifdef PLATFORM_WIN32
1256 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1258 exe_image = mono_image_open (exe_filename, NULL);
1260 mono_fixup_exe_image (exe_image);
1262 } else if (runtime_version != NULL) {
1263 runtimes [0] = get_runtime_by_version (runtime_version);
1264 runtimes [1] = NULL;
1267 if (runtimes [0] == NULL) {
1268 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1269 runtimes [0] = default_runtime;
1270 runtimes [1] = NULL;
1271 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1272 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1275 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1276 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1277 current_runtime = runtimes [n];
1278 ass = mono_assembly_load_corlib (current_runtime, &status);
1279 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1284 /* Now that we have a runtime, set the policy for unhandled exceptions */
1285 if (mono_get_runtime_info ()->framework_version [0] < '2') {
1286 mono_runtime_unhandled_exception_policy_set (MONO_UNHANLED_POLICY_LEGACY);
1289 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1291 case MONO_IMAGE_ERROR_ERRNO: {
1292 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1293 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1294 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1295 g_free (corlib_file);
1298 case MONO_IMAGE_IMAGE_INVALID:
1299 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1300 mono_assembly_getrootdir ());
1302 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1303 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1304 mono_assembly_getrootdir ());
1307 /* to suppress compiler warning */
1313 mono_defaults.corlib = mono_assembly_get_image (ass);
1315 mono_defaults.object_class = mono_class_from_name (
1316 mono_defaults.corlib, "System", "Object");
1317 g_assert (mono_defaults.object_class != 0);
1319 mono_defaults.void_class = mono_class_from_name (
1320 mono_defaults.corlib, "System", "Void");
1321 g_assert (mono_defaults.void_class != 0);
1323 mono_defaults.boolean_class = mono_class_from_name (
1324 mono_defaults.corlib, "System", "Boolean");
1325 g_assert (mono_defaults.boolean_class != 0);
1327 mono_defaults.byte_class = mono_class_from_name (
1328 mono_defaults.corlib, "System", "Byte");
1329 g_assert (mono_defaults.byte_class != 0);
1331 mono_defaults.sbyte_class = mono_class_from_name (
1332 mono_defaults.corlib, "System", "SByte");
1333 g_assert (mono_defaults.sbyte_class != 0);
1335 mono_defaults.int16_class = mono_class_from_name (
1336 mono_defaults.corlib, "System", "Int16");
1337 g_assert (mono_defaults.int16_class != 0);
1339 mono_defaults.uint16_class = mono_class_from_name (
1340 mono_defaults.corlib, "System", "UInt16");
1341 g_assert (mono_defaults.uint16_class != 0);
1343 mono_defaults.int32_class = mono_class_from_name (
1344 mono_defaults.corlib, "System", "Int32");
1345 g_assert (mono_defaults.int32_class != 0);
1347 mono_defaults.uint32_class = mono_class_from_name (
1348 mono_defaults.corlib, "System", "UInt32");
1349 g_assert (mono_defaults.uint32_class != 0);
1351 mono_defaults.uint_class = mono_class_from_name (
1352 mono_defaults.corlib, "System", "UIntPtr");
1353 g_assert (mono_defaults.uint_class != 0);
1355 mono_defaults.int_class = mono_class_from_name (
1356 mono_defaults.corlib, "System", "IntPtr");
1357 g_assert (mono_defaults.int_class != 0);
1359 mono_defaults.int64_class = mono_class_from_name (
1360 mono_defaults.corlib, "System", "Int64");
1361 g_assert (mono_defaults.int64_class != 0);
1363 mono_defaults.uint64_class = mono_class_from_name (
1364 mono_defaults.corlib, "System", "UInt64");
1365 g_assert (mono_defaults.uint64_class != 0);
1367 mono_defaults.single_class = mono_class_from_name (
1368 mono_defaults.corlib, "System", "Single");
1369 g_assert (mono_defaults.single_class != 0);
1371 mono_defaults.double_class = mono_class_from_name (
1372 mono_defaults.corlib, "System", "Double");
1373 g_assert (mono_defaults.double_class != 0);
1375 mono_defaults.char_class = mono_class_from_name (
1376 mono_defaults.corlib, "System", "Char");
1377 g_assert (mono_defaults.char_class != 0);
1379 mono_defaults.string_class = mono_class_from_name (
1380 mono_defaults.corlib, "System", "String");
1381 g_assert (mono_defaults.string_class != 0);
1383 mono_defaults.enum_class = mono_class_from_name (
1384 mono_defaults.corlib, "System", "Enum");
1385 g_assert (mono_defaults.enum_class != 0);
1387 mono_defaults.array_class = mono_class_from_name (
1388 mono_defaults.corlib, "System", "Array");
1389 g_assert (mono_defaults.array_class != 0);
1391 mono_defaults.delegate_class = mono_class_from_name (
1392 mono_defaults.corlib, "System", "Delegate");
1393 g_assert (mono_defaults.delegate_class != 0 );
1395 mono_defaults.multicastdelegate_class = mono_class_from_name (
1396 mono_defaults.corlib, "System", "MulticastDelegate");
1397 g_assert (mono_defaults.multicastdelegate_class != 0 );
1399 mono_defaults.asyncresult_class = mono_class_from_name (
1400 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1402 g_assert (mono_defaults.asyncresult_class != 0 );
1404 mono_defaults.waithandle_class = mono_class_from_name (
1405 mono_defaults.corlib, "System.Threading", "WaitHandle");
1406 g_assert (mono_defaults.waithandle_class != 0 );
1408 mono_defaults.typehandle_class = mono_class_from_name (
1409 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1410 g_assert (mono_defaults.typehandle_class != 0);
1412 mono_defaults.methodhandle_class = mono_class_from_name (
1413 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1414 g_assert (mono_defaults.methodhandle_class != 0);
1416 mono_defaults.fieldhandle_class = mono_class_from_name (
1417 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1418 g_assert (mono_defaults.fieldhandle_class != 0);
1420 mono_defaults.systemtype_class = mono_class_from_name (
1421 mono_defaults.corlib, "System", "Type");
1422 g_assert (mono_defaults.systemtype_class != 0);
1424 mono_defaults.monotype_class = mono_class_from_name (
1425 mono_defaults.corlib, "System", "MonoType");
1426 g_assert (mono_defaults.monotype_class != 0);
1428 mono_defaults.exception_class = mono_class_from_name (
1429 mono_defaults.corlib, "System", "Exception");
1430 g_assert (mono_defaults.exception_class != 0);
1432 mono_defaults.threadabortexception_class = mono_class_from_name (
1433 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1434 g_assert (mono_defaults.threadabortexception_class != 0);
1436 mono_defaults.thread_class = mono_class_from_name (
1437 mono_defaults.corlib, "System.Threading", "Thread");
1438 g_assert (mono_defaults.thread_class != 0);
1440 mono_defaults.appdomain_class = mono_class_from_name (
1441 mono_defaults.corlib, "System", "AppDomain");
1442 g_assert (mono_defaults.appdomain_class != 0);
1444 mono_defaults.transparent_proxy_class = mono_class_from_name (
1445 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1446 g_assert (mono_defaults.transparent_proxy_class != 0);
1448 mono_defaults.real_proxy_class = mono_class_from_name (
1449 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1450 g_assert (mono_defaults.real_proxy_class != 0);
1452 mono_defaults.mono_method_message_class = mono_class_from_name (
1453 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1454 g_assert (mono_defaults.mono_method_message_class != 0);
1456 mono_defaults.field_info_class = mono_class_from_name (
1457 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1458 g_assert (mono_defaults.field_info_class != 0);
1460 mono_defaults.method_info_class = mono_class_from_name (
1461 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1462 g_assert (mono_defaults.method_info_class != 0);
1464 mono_defaults.stringbuilder_class = mono_class_from_name (
1465 mono_defaults.corlib, "System.Text", "StringBuilder");
1466 g_assert (mono_defaults.stringbuilder_class != 0);
1468 mono_defaults.math_class = mono_class_from_name (
1469 mono_defaults.corlib, "System", "Math");
1470 g_assert (mono_defaults.math_class != 0);
1472 mono_defaults.stack_frame_class = mono_class_from_name (
1473 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1474 g_assert (mono_defaults.stack_frame_class != 0);
1476 mono_defaults.stack_trace_class = mono_class_from_name (
1477 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1478 g_assert (mono_defaults.stack_trace_class != 0);
1480 mono_defaults.marshal_class = mono_class_from_name (
1481 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1482 g_assert (mono_defaults.marshal_class != 0);
1484 mono_defaults.iserializeable_class = mono_class_from_name (
1485 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1486 g_assert (mono_defaults.iserializeable_class != 0);
1488 mono_defaults.serializationinfo_class = mono_class_from_name (
1489 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1490 g_assert (mono_defaults.serializationinfo_class != 0);
1492 mono_defaults.streamingcontext_class = mono_class_from_name (
1493 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1494 g_assert (mono_defaults.streamingcontext_class != 0);
1496 mono_defaults.typed_reference_class = mono_class_from_name (
1497 mono_defaults.corlib, "System", "TypedReference");
1498 g_assert (mono_defaults.typed_reference_class != 0);
1500 mono_defaults.argumenthandle_class = mono_class_from_name (
1501 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1502 g_assert (mono_defaults.argumenthandle_class != 0);
1504 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1505 mono_defaults.corlib, "System", "MarshalByRefObject");
1506 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1508 mono_defaults.monitor_class = mono_class_from_name (
1509 mono_defaults.corlib, "System.Threading", "Monitor");
1510 g_assert (mono_defaults.monitor_class != 0);
1512 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1513 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1514 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1516 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1517 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1519 mono_defaults.executioncontext_class = mono_class_from_name (
1520 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1522 mono_defaults.internals_visible_class = mono_class_from_name (
1523 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1526 * mscorlib needs a little help, only now it can load its friends list (after we have
1527 * loaded the InternalsVisibleToAttribute), load it now
1529 mono_assembly_load_friends (ass);
1531 mono_defaults.safehandle_class = mono_class_from_name (
1532 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1534 mono_defaults.handleref_class = mono_class_from_name (
1535 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1537 mono_defaults.attribute_class = mono_class_from_name (
1538 mono_defaults.corlib, "System", "Attribute");
1540 mono_defaults.customattribute_data_class = mono_class_from_name (
1541 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1543 /* these are initialized lazily when COM features are used */
1544 mono_defaults.variant_class = NULL;
1545 mono_defaults.com_object_class = NULL;
1546 mono_defaults.com_interop_proxy_class = NULL;
1547 mono_defaults.iunknown_class = NULL;
1548 mono_defaults.idispatch_class = NULL;
1551 * Note that mono_defaults.generic_*_class is only non-NULL if we're
1552 * using the 2.0 corlib.
1554 mono_class_init (mono_defaults.array_class);
1555 mono_defaults.generic_nullable_class = mono_class_from_name (
1556 mono_defaults.corlib, "System", "Nullable`1");
1557 mono_defaults.generic_ilist_class = mono_class_from_name (
1558 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1560 domain->friendly_name = g_path_get_basename (filename);
1562 _mono_debug_init_corlib (domain);
1570 * Creates the initial application domain and initializes the mono_defaults
1572 * This function is guaranteed to not run any IL code.
1573 * The runtime is initialized using the default runtime version.
1575 * Returns: the initial domain.
1578 mono_init (const char *domain_name)
1580 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1584 * mono_init_from_assembly:
1586 * Creates the initial application domain and initializes the mono_defaults
1588 * This function is guaranteed to not run any IL code.
1589 * The runtime is initialized using the runtime version required by the
1590 * provided executable. The version is determined by looking at the exe
1591 * configuration file and the version PE field)
1593 * Returns: the initial domain.
1596 mono_init_from_assembly (const char *domain_name, const char *filename)
1598 return mono_init_internal (domain_name, filename, NULL);
1602 * mono_init_version:
1604 * Creates the initial application domain and initializes the mono_defaults
1606 * This function is guaranteed to not run any IL code.
1607 * The runtime is initialized using the provided rutime version.
1609 * Returns: the initial domain.
1612 mono_init_version (const char *domain_name, const char *version)
1614 return mono_init_internal (domain_name, NULL, version);
1618 * mono_init_com_types:
1620 * Initializes all types needed for COM Interop in mono_defaults structure.
1623 mono_init_com_types (void)
1625 static gboolean initialized = FALSE;
1630 /* FIXME: do I need some threading protection here */
1632 g_assert (mono_defaults.corlib);
1634 mono_defaults.variant_class = mono_class_from_name (
1635 mono_defaults.corlib, "System", "Variant");
1636 g_assert (mono_defaults.variant_class != 0);
1638 mono_defaults.com_object_class = mono_class_from_name (
1639 mono_defaults.corlib, "System", "__ComObject");
1640 g_assert (mono_defaults.com_object_class != 0);
1642 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1643 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1644 g_assert (mono_defaults.com_interop_proxy_class != 0);
1646 mono_defaults.iunknown_class = mono_class_from_name (
1647 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1648 g_assert (mono_defaults.iunknown_class != 0);
1650 mono_defaults.idispatch_class = mono_class_from_name (
1651 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1652 g_assert (mono_defaults.idispatch_class != 0);
1660 * Cleans up all metadata modules.
1665 mono_close_exe_image ();
1667 mono_loader_cleanup ();
1668 mono_classes_cleanup ();
1669 mono_assemblies_cleanup ();
1670 mono_images_cleanup ();
1671 mono_debug_cleanup ();
1672 mono_raw_buffer_cleanup ();
1673 mono_metadata_cleanup ();
1675 TlsFree (appdomain_thread_id);
1676 DeleteCriticalSection (&appdomains_mutex);
1680 mono_close_exe_image (void)
1683 mono_image_close (exe_image);
1687 * mono_get_root_domain:
1689 * The root AppDomain is the initial domain created by the runtime when it is
1690 * initialized. Programs execute on this AppDomain, but can create new ones
1691 * later. Currently there is no unmanaged API to create new AppDomains, this
1692 * must be done from managed code.
1694 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1697 mono_get_root_domain (void)
1699 return mono_root_domain;
1705 * Returns: the current domain, to obtain the root domain use
1706 * mono_get_root_domain().
1711 return GET_APPDOMAIN ();
1715 * mono_domain_set_internal:
1716 * @domain: the new domain
1718 * Sets the current domain to @domain.
1721 mono_domain_set_internal (MonoDomain *domain)
1723 SET_APPDOMAIN (domain);
1724 SET_APPCONTEXT (domain->default_context);
1728 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1734 * Create a copy of the data to avoid calling the user callback
1735 * inside the lock because that could lead to deadlocks.
1736 * We can do this because this function is not perf. critical.
1738 mono_appdomains_lock ();
1739 size = appdomain_list_size;
1740 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1741 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1742 mono_appdomains_unlock ();
1744 for (i = 0; i < size; ++i) {
1746 func (copy [i], user_data);
1749 mono_gc_free_fixed (copy);
1753 * mono_domain_assembly_open:
1754 * @domain: the application domain
1755 * @name: file name of the assembly
1757 * fixme: maybe we should integrate this with mono_assembly_open ??
1760 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1765 mono_domain_assemblies_lock (domain);
1766 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1768 if (strcmp (name, ass->aname.name) == 0) {
1769 mono_domain_assemblies_unlock (domain);
1773 mono_domain_assemblies_unlock (domain);
1775 if (!(ass = mono_assembly_open (name, NULL)))
1782 mono_domain_lookup_shared_generic (MonoDomain *domain, MonoMethod *method)
1784 if (!domain->shared_generics_hash)
1787 return g_hash_table_lookup (domain->shared_generics_hash, method);
1791 mono_domain_register_shared_generic (MonoDomain *domain, MonoMethod *method, MonoJitInfo *jit_info)
1793 if (!domain->shared_generics_hash)
1794 domain->shared_generics_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1796 g_assert (domain->shared_generics_hash);
1798 g_hash_table_insert (domain->shared_generics_hash, method, jit_info);
1802 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
1804 MonoJitDynamicMethodInfo *di = value;
1805 mono_code_manager_destroy (di->code_mp);
1810 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
1812 g_slist_free (value);
1816 mono_domain_free (MonoDomain *domain, gboolean force)
1818 int code_size, code_alloc;
1820 if ((domain == mono_root_domain) && !force) {
1821 g_warning ("cant unload root domain");
1825 if (mono_dont_free_domains)
1828 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1830 mono_debug_domain_unload (domain);
1832 mono_appdomains_lock ();
1833 appdomains_list [domain->domain_id] = NULL;
1834 mono_appdomains_unlock ();
1836 /* FIXME: free delegate_hash_table when it's used */
1837 if (domain->search_path) {
1838 g_strfreev (domain->search_path);
1839 domain->search_path = NULL;
1841 domain->create_proxy_for_type_method = NULL;
1842 domain->private_invoke_method = NULL;
1843 domain->default_context = NULL;
1844 domain->out_of_memory_ex = NULL;
1845 domain->null_reference_ex = NULL;
1846 domain->stack_overflow_ex = NULL;
1847 domain->entry_assembly = NULL;
1848 /* must do this early as it accesses fields and types */
1849 if (domain->special_static_fields) {
1850 mono_alloc_special_static_data_free (domain->special_static_fields);
1851 g_hash_table_destroy (domain->special_static_fields);
1852 domain->special_static_fields = NULL;
1854 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1855 MonoAssembly *ass = tmp->data;
1856 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);
1857 mono_assembly_close (ass);
1859 g_slist_free (domain->domain_assemblies);
1860 domain->domain_assemblies = NULL;
1862 g_free (domain->friendly_name);
1863 domain->friendly_name = NULL;
1864 mono_g_hash_table_destroy (domain->env);
1866 g_hash_table_destroy (domain->class_vtable_hash);
1867 domain->class_vtable_hash = NULL;
1868 g_hash_table_destroy (domain->proxy_vtable_hash);
1869 domain->proxy_vtable_hash = NULL;
1870 if (domain->static_data_array) {
1871 mono_gc_free_fixed (domain->static_data_array);
1872 domain->static_data_array = NULL;
1874 mono_internal_hash_table_destroy (&domain->jit_code_hash);
1875 if (domain->dynamic_code_hash) {
1876 g_hash_table_foreach (domain->dynamic_code_hash, dynamic_method_info_free, NULL);
1877 g_hash_table_destroy (domain->dynamic_code_hash);
1878 domain->dynamic_code_hash = NULL;
1880 mono_g_hash_table_destroy (domain->ldstr_table);
1881 domain->ldstr_table = NULL;
1884 * There might still be jit info tables of this domain which
1885 * are not freed. Since the domain cannot be in use anymore,
1886 * this will free them.
1888 mono_thread_hazardous_try_free_all ();
1889 g_assert (domain->num_jit_info_tables == 1);
1890 jit_info_table_free (domain->jit_info_table);
1891 domain->jit_info_table = NULL;
1892 g_assert (!domain->jit_info_free_queue);
1894 /* collect statistics */
1895 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
1896 total_domain_code_alloc += code_alloc;
1897 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
1898 max_domain_code_size = MAX (max_domain_code_size, code_size);
1900 #ifdef DEBUG_DOMAIN_UNLOAD
1901 mono_mempool_invalidate (domain->mp);
1902 mono_code_manager_invalidate (domain->code_mp);
1904 mono_mempool_destroy (domain->mp);
1906 mono_code_manager_destroy (domain->code_mp);
1907 domain->code_mp = NULL;
1909 if (domain->jump_target_hash) {
1910 g_hash_table_foreach (domain->jump_target_hash, delete_jump_list, NULL);
1911 g_hash_table_destroy (domain->jump_target_hash);
1912 domain->jump_target_hash = NULL;
1914 if (domain->type_hash) {
1915 mono_g_hash_table_destroy (domain->type_hash);
1916 domain->type_hash = NULL;
1918 if (domain->refobject_hash) {
1919 mono_g_hash_table_destroy (domain->refobject_hash);
1920 domain->refobject_hash = NULL;
1922 if (domain->type_init_exception_hash) {
1923 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1924 domain->type_init_exception_hash = NULL;
1926 g_hash_table_destroy (domain->class_init_trampoline_hash);
1927 domain->class_init_trampoline_hash = NULL;
1928 g_hash_table_destroy (domain->jump_trampoline_hash);
1929 domain->jump_trampoline_hash = NULL;
1930 g_hash_table_destroy (domain->finalizable_objects_hash);
1931 domain->finalizable_objects_hash = NULL;
1932 g_hash_table_destroy (domain->jit_trampoline_hash);
1933 domain->jit_trampoline_hash = NULL;
1934 g_hash_table_destroy (domain->delegate_trampoline_hash);
1935 domain->delegate_trampoline_hash = NULL;
1936 if (domain->shared_generics_hash) {
1937 g_hash_table_destroy (domain->shared_generics_hash);
1938 domain->shared_generics_hash = NULL;
1940 if (domain->method_rgctx_hash) {
1941 g_hash_table_destroy (domain->method_rgctx_hash);
1942 domain->method_rgctx_hash = NULL;
1944 if (domain->method_code_hash) {
1945 g_hash_table_destroy (domain->method_code_hash);
1946 domain->method_code_hash = NULL;
1949 DeleteCriticalSection (&domain->assemblies_lock);
1950 DeleteCriticalSection (&domain->jit_code_hash_lock);
1951 DeleteCriticalSection (&domain->lock);
1952 domain->setup = NULL;
1954 /* FIXME: anything else required ? */
1956 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
1958 mono_gc_free_fixed (domain);
1960 if ((domain == mono_root_domain))
1961 mono_root_domain = NULL;
1965 * mono_domain_get_id:
1968 * Returns: the a domain for a specific domain id.
1971 mono_domain_get_by_id (gint32 domainid)
1973 MonoDomain * domain;
1975 mono_appdomains_lock ();
1976 if (domainid < appdomain_list_size)
1977 domain = appdomains_list [domainid];
1980 mono_appdomains_unlock ();
1986 mono_domain_get_id (MonoDomain *domain)
1988 return domain->domain_id;
1992 mono_context_set (MonoAppContext * new_context)
1994 SET_APPCONTEXT (new_context);
1998 mono_context_get (void)
2000 return GET_APPCONTEXT ();
2003 /* LOCKING: the caller holds the lock for this domain */
2005 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
2007 /* The first entry in the array is the index of the next free slot
2008 * and the total size of the array
2011 if (domain->static_data_array) {
2012 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
2013 next = GPOINTER_TO_INT (domain->static_data_array [0]);
2015 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), NULL);
2016 memcpy (new_array, domain->static_data_array, sizeof (gpointer) * size);
2018 new_array [1] = GINT_TO_POINTER (size);
2019 mono_gc_free_fixed (domain->static_data_array);
2020 domain->static_data_array = new_array;
2024 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, NULL);
2026 new_array [0] = GINT_TO_POINTER (next);
2027 new_array [1] = GINT_TO_POINTER (size);
2028 domain->static_data_array = new_array;
2030 domain->static_data_array [next++] = data;
2031 domain->static_data_array [0] = GINT_TO_POINTER (next);
2035 mono_get_corlib (void)
2037 return mono_defaults.corlib;
2041 mono_get_object_class (void)
2043 return mono_defaults.object_class;
2047 mono_get_byte_class (void)
2049 return mono_defaults.byte_class;
2053 mono_get_void_class (void)
2055 return mono_defaults.void_class;
2059 mono_get_boolean_class (void)
2061 return mono_defaults.boolean_class;
2065 mono_get_sbyte_class (void)
2067 return mono_defaults.sbyte_class;
2071 mono_get_int16_class (void)
2073 return mono_defaults.int16_class;
2077 mono_get_uint16_class (void)
2079 return mono_defaults.uint16_class;
2083 mono_get_int32_class (void)
2085 return mono_defaults.int32_class;
2089 mono_get_uint32_class (void)
2091 return mono_defaults.uint32_class;
2095 mono_get_intptr_class (void)
2097 return mono_defaults.int_class;
2101 mono_get_uintptr_class (void)
2103 return mono_defaults.uint_class;
2107 mono_get_int64_class (void)
2109 return mono_defaults.int64_class;
2113 mono_get_uint64_class (void)
2115 return mono_defaults.uint64_class;
2119 mono_get_single_class (void)
2121 return mono_defaults.single_class;
2125 mono_get_double_class (void)
2127 return mono_defaults.double_class;
2131 mono_get_char_class (void)
2133 return mono_defaults.char_class;
2137 mono_get_string_class (void)
2139 return mono_defaults.string_class;
2143 mono_get_enum_class (void)
2145 return mono_defaults.enum_class;
2149 mono_get_array_class (void)
2151 return mono_defaults.array_class;
2155 mono_get_thread_class (void)
2157 return mono_defaults.thread_class;
2161 mono_get_exception_class (void)
2163 return mono_defaults.exception_class;
2167 static char* get_attribute_value (const gchar **attribute_names,
2168 const gchar **attribute_values,
2169 const char *att_name)
2172 for (n=0; attribute_names[n] != NULL; n++) {
2173 if (strcmp (attribute_names[n], att_name) == 0)
2174 return g_strdup (attribute_values[n]);
2179 static void start_element (GMarkupParseContext *context,
2180 const gchar *element_name,
2181 const gchar **attribute_names,
2182 const gchar **attribute_values,
2186 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2188 if (strcmp (element_name, "configuration") == 0) {
2189 app_config->configuration_count++;
2192 if (strcmp (element_name, "startup") == 0) {
2193 app_config->startup_count++;
2197 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2200 if (strcmp (element_name, "requiredRuntime") == 0) {
2201 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2202 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2203 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2204 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2208 static void end_element (GMarkupParseContext *context,
2209 const gchar *element_name,
2213 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2215 if (strcmp (element_name, "configuration") == 0) {
2216 app_config->configuration_count--;
2217 } else if (strcmp (element_name, "startup") == 0) {
2218 app_config->startup_count--;
2222 static const GMarkupParser
2231 static AppConfigInfo *
2232 app_config_parse (const char *exe_filename)
2234 AppConfigInfo *app_config;
2235 GMarkupParseContext *context;
2239 const char *bundled_config;
2240 char *config_filename;
2242 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2244 if (bundled_config) {
2245 text = g_strdup (bundled_config);
2246 len = strlen (text);
2248 config_filename = g_strconcat (exe_filename, ".config", NULL);
2250 if (stat (config_filename, &buf) != 0) {
2251 g_free (config_filename);
2255 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2256 g_free (config_filename);
2259 g_free (config_filename);
2262 app_config = g_new0 (AppConfigInfo, 1);
2264 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2265 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2266 g_markup_parse_context_end_parse (context, NULL);
2268 g_markup_parse_context_free (context);
2274 app_config_free (AppConfigInfo* app_config)
2277 GSList *list = app_config->supported_runtimes;
2278 while (list != NULL) {
2279 rt = (char*)list->data;
2281 list = g_slist_next (list);
2283 g_slist_free (app_config->supported_runtimes);
2284 g_free (app_config->required_runtime);
2285 g_free (app_config);
2289 static const MonoRuntimeInfo*
2290 get_runtime_by_version (const char *version)
2293 int max = G_N_ELEMENTS (supported_runtimes);
2295 for (n=0; n<max; n++) {
2296 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2297 return &supported_runtimes[n];
2303 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2305 AppConfigInfo* app_config;
2307 const MonoRuntimeInfo* runtime = NULL;
2308 MonoImage *image = NULL;
2310 app_config = app_config_parse (exe_file);
2312 if (app_config != NULL) {
2313 /* Check supportedRuntime elements, if none is supported, fail.
2314 * If there are no such elements, look for a requiredRuntime element.
2316 if (app_config->supported_runtimes != NULL) {
2318 GSList *list = app_config->supported_runtimes;
2319 while (list != NULL) {
2320 version = (char*) list->data;
2321 runtime = get_runtime_by_version (version);
2322 if (runtime != NULL)
2323 runtimes [n++] = runtime;
2324 list = g_slist_next (list);
2326 runtimes [n] = NULL;
2327 app_config_free (app_config);
2331 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2332 if (app_config->required_runtime != NULL) {
2333 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2334 runtimes [1] = NULL;
2335 app_config_free (app_config);
2338 app_config_free (app_config);
2341 /* Look for a runtime with the exact version */
2342 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2345 image = mono_image_open (exe_file, NULL);
2347 if (image == NULL) {
2348 /* The image is wrong or the file was not found. In this case return
2349 * a default runtime and leave to the initialization method the work of
2350 * reporting the error.
2352 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2353 runtimes [1] = NULL;
2359 runtimes [0] = get_runtime_by_version (image->version);
2360 runtimes [1] = NULL;
2365 * mono_get_runtime_info:
2367 * Returns: the version of the current runtime instance.
2369 const MonoRuntimeInfo*
2370 mono_get_runtime_info (void)
2372 return current_runtime;
2376 mono_debugger_check_runtime_version (const char *filename)
2378 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2379 const MonoRuntimeInfo *rinfo;
2382 get_runtimes_from_exe (filename, &image, runtimes);
2383 rinfo = runtimes [0];
2386 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2388 if (rinfo != current_runtime)
2389 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2390 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2391 filename, rinfo->runtime_version);