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 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
72 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
73 static CRITICAL_SECTION appdomains_mutex;
75 static MonoDomain *mono_root_domain = NULL;
78 static int max_domain_code_size = 0;
79 static int max_domain_code_alloc = 0;
80 static int total_domain_code_alloc = 0;
82 /* AppConfigInfo: Information about runtime versions supported by an
86 GSList *supported_runtimes;
87 char *required_runtime;
88 int configuration_count;
93 * AotModuleInfo: Contains information about AOT modules.
100 static const MonoRuntimeInfo *current_runtime = NULL;
102 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
105 * Contains information about AOT loaded code.
107 static MonoAotModuleInfoTable *aot_modules = NULL;
109 /* This is the list of runtime versions supported by this JIT.
111 static const MonoRuntimeInfo supported_runtimes[] = {
112 {"v1.0.3705", "1.0", { {1,0,5000,0}, {7,0,5000,0} } },
113 {"v1.1.4322", "1.0", { {1,0,5000,0}, {7,0,5000,0} } },
114 {"v2.0.50215","2.0", { {2,0,0,0}, {8,0,0,0} } },
115 {"v2.0.50727","2.0", { {2,0,0,0}, {8,0,0,0} } },
116 {"moonlight", "2.1", { {2,0,5,0}, {9,0,0,0} } },
120 /* The stable runtime version */
121 #define DEFAULT_RUNTIME_VERSION "v1.1.4322"
123 /* This is intentionally not in the header file, so people don't misuse it. */
124 extern void _mono_debug_init_corlib (MonoDomain *domain);
127 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
129 static const MonoRuntimeInfo*
130 get_runtime_by_version (const char *version);
133 mono_jit_info_find_aot_module (guint8* addr);
136 mono_domain_get_tls_key (void)
138 return appdomain_thread_id;
142 mono_domain_get_tls_offset (void)
145 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
146 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
151 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
152 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
153 #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)
155 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
156 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
158 #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
159 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
161 #define JIT_INFO_TABLE_HAZARD_INDEX 0
162 #define JIT_INFO_HAZARD_INDEX 1
165 jit_info_table_num_elements (MonoJitInfoTable *table)
168 int num_elements = 0;
170 for (i = 0; i < table->num_chunks; ++i) {
171 MonoJitInfoTableChunk *chunk = table->chunks [i];
172 int chunk_num_elements = chunk->num_elements;
175 for (j = 0; j < chunk_num_elements; ++j) {
176 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
184 static MonoJitInfoTableChunk*
185 jit_info_table_new_chunk (void)
187 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
193 static MonoJitInfoTable *
194 jit_info_table_new (MonoDomain *domain)
196 MonoJitInfoTable *table = g_malloc0 (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*));
198 table->domain = domain;
199 table->num_chunks = 1;
200 table->chunks [0] = jit_info_table_new_chunk ();
206 jit_info_table_free (MonoJitInfoTable *table)
209 int num_chunks = table->num_chunks;
210 MonoDomain *domain = table->domain;
212 mono_domain_lock (domain);
214 table->domain->num_jit_info_tables--;
215 if (table->domain->num_jit_info_tables <= 1) {
218 for (list = table->domain->jit_info_free_queue; list; list = list->next)
221 g_slist_free (table->domain->jit_info_free_queue);
222 table->domain->jit_info_free_queue = NULL;
225 /* At this point we assume that there are no other threads
226 still accessing the table, so we don't have to worry about
227 hazardous pointers. */
229 for (i = 0; i < num_chunks; ++i) {
230 MonoJitInfoTableChunk *chunk = table->chunks [i];
234 if (--chunk->refcount > 0)
237 num_elements = chunk->num_elements;
238 for (j = 0; j < num_elements; ++j) {
239 MonoJitInfo *ji = chunk->data [j];
241 if (IS_JIT_INFO_TOMBSTONE (ji))
248 mono_domain_unlock (domain);
253 /* Can be called with hp==NULL, in which case it acts as an ordinary
254 pointer fetch. It's used that way indirectly from
255 mono_jit_info_table_add(), which doesn't have to care about hazards
256 because it holds the respective domain lock. */
258 get_hazardous_pointer (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index)
263 /* Get the pointer */
265 /* If we don't have hazard pointers just return the
269 /* Make it hazardous */
270 mono_hazard_pointer_set (hp, hazard_index, p);
271 /* Check that it's still the same. If not, try
274 mono_hazard_pointer_clear (hp, hazard_index);
283 /* The jit_info_table is sorted in ascending order by the end
284 * addresses of the compiled methods. The reason why we have to do
285 * this is that once we introduce tombstones, it becomes possible for
286 * code ranges to overlap, and if we sort by code start and insert at
287 * the back of the table, we cannot guarantee that we won't overlook
290 * There are actually two possible ways to do the sorting and
291 * inserting which work with our lock-free mechanism:
293 * 1. Sort by start address and insert at the front. When looking for
294 * an entry, find the last one with a start address lower than the one
295 * you're looking for, then work your way to the front of the table.
297 * 2. Sort by end address and insert at the back. When looking for an
298 * entry, find the first one with an end address higher than the one
299 * you're looking for, then work your way to the end of the table.
301 * We chose the latter out of convenience.
304 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
306 int left = 0, right = table->num_chunks;
308 g_assert (left < right);
311 int pos = (left + right) / 2;
312 MonoJitInfoTableChunk *chunk = table->chunks [pos];
314 if (addr < chunk->last_code_end)
318 } while (left < right);
319 g_assert (left == right);
321 if (left >= table->num_chunks)
322 return table->num_chunks - 1;
327 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
329 int left = 0, right = chunk->num_elements;
331 while (left < right) {
332 int pos = (left + right) / 2;
333 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
334 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
341 g_assert (left == right);
347 mono_jit_info_table_find (MonoDomain *domain, char *addr)
349 MonoJitInfoTable *table;
352 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
354 ++mono_stats.jit_info_table_lookup_count;
356 /* First we have to get the domain's jit_info_table. This is
357 complicated by the fact that a writer might substitute a
358 new table and free the old one. What the writer guarantees
359 us is that it looks at the hazard pointers after it has
360 changed the jit_info_table pointer. So, if we guard the
361 table by a hazard pointer and make sure that the pointer is
362 still there after we've made it hazardous, we don't have to
363 worry about the writer freeing the table. */
364 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
366 chunk_pos = jit_info_table_index (table, (gint8*)addr);
367 g_assert (chunk_pos < table->num_chunks);
369 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
371 /* We now have a position that's very close to that of the
372 first element whose end address is higher than the one
373 we're looking for. If we don't have the exact position,
374 then we have a position below that one, so we'll just
375 search upward until we find our element. */
377 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
379 while (pos < chunk->num_elements) {
380 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
384 if (IS_JIT_INFO_TOMBSTONE (ji)) {
385 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
388 if ((gint8*)addr >= (gint8*)ji->code_start
389 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
390 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
391 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
395 /* If we find a non-tombstone element which is already
396 beyond what we're looking for, we have to end the
398 if ((gint8*)addr < (gint8*)ji->code_start)
404 } while (chunk_pos < table->num_chunks);
406 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
407 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
409 /* maybe it is shared code, so we also search in the root domain */
411 if (domain != mono_root_domain)
412 ji = mono_jit_info_table_find (mono_root_domain, addr);
415 /* Maybe its an AOT module */
416 MonoImage *image = mono_jit_info_find_aot_module ((guint8*)addr);
418 ji = jit_info_find_in_aot_func (domain, image, addr);
424 static G_GNUC_UNUSED void
425 jit_info_table_check (MonoJitInfoTable *table)
429 for (i = 0; i < table->num_chunks; ++i) {
430 MonoJitInfoTableChunk *chunk = table->chunks [i];
433 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
434 if (chunk->refcount > 10)
435 printf("warning: chunk refcount is %d\n", chunk->refcount);
436 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
438 for (j = 0; j < chunk->num_elements; ++j) {
439 MonoJitInfo *this = chunk->data [j];
442 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
444 if (j < chunk->num_elements - 1)
445 next = chunk->data [j + 1];
446 else if (i < table->num_chunks - 1) {
449 for (k = i + 1; k < table->num_chunks; ++k)
450 if (table->chunks [k]->num_elements > 0)
453 if (k >= table->num_chunks)
456 g_assert (table->chunks [k]->num_elements > 0);
457 next = table->chunks [k]->data [0];
461 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
466 static MonoJitInfoTable*
467 jit_info_table_realloc (MonoJitInfoTable *old)
470 int num_elements = jit_info_table_num_elements (old);
473 int new_chunk, new_element;
474 MonoJitInfoTable *new;
476 /* number of needed places for elements needed */
477 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
478 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
480 new = g_malloc (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*) * num_chunks);
481 new->domain = old->domain;
482 new->num_chunks = num_chunks;
484 for (i = 0; i < num_chunks; ++i)
485 new->chunks [i] = jit_info_table_new_chunk ();
489 for (i = 0; i < old->num_chunks; ++i) {
490 MonoJitInfoTableChunk *chunk = old->chunks [i];
491 int chunk_num_elements = chunk->num_elements;
494 for (j = 0; j < chunk_num_elements; ++j) {
495 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
496 g_assert (new_chunk < num_chunks);
497 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
498 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
499 new->chunks [new_chunk]->num_elements = new_element;
507 if (new_chunk < num_chunks) {
508 g_assert (new_chunk == num_chunks - 1);
509 new->chunks [new_chunk]->num_elements = new_element;
510 g_assert (new->chunks [new_chunk]->num_elements > 0);
513 for (i = 0; i < num_chunks; ++i) {
514 MonoJitInfoTableChunk *chunk = new->chunks [i];
515 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
517 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
524 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
526 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
527 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
529 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
531 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
532 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
534 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
535 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
537 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
538 + new1->data [new1->num_elements - 1]->code_size;
539 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
540 + new2->data [new2->num_elements - 1]->code_size;
546 static MonoJitInfoTable*
547 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
549 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
550 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
553 new_table->domain = table->domain;
554 new_table->num_chunks = table->num_chunks + 1;
557 for (i = 0; i < table->num_chunks; ++i) {
558 if (table->chunks [i] == chunk) {
559 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
562 new_table->chunks [j] = table->chunks [i];
563 ++new_table->chunks [j]->refcount;
568 g_assert (j == new_table->num_chunks);
573 static MonoJitInfoTableChunk*
574 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
576 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
580 for (i = 0; i < old->num_elements; ++i) {
581 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
582 new->data [j++] = old->data [i];
585 new->num_elements = j;
586 if (new->num_elements > 0)
587 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
589 new->last_code_end = old->last_code_end;
594 static MonoJitInfoTable*
595 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
597 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
598 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
601 new_table->domain = table->domain;
602 new_table->num_chunks = table->num_chunks;
605 for (i = 0; i < table->num_chunks; ++i) {
606 if (table->chunks [i] == chunk)
607 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
609 new_table->chunks [j] = table->chunks [i];
610 ++new_table->chunks [j]->refcount;
615 g_assert (j == new_table->num_chunks);
620 /* As we add an element to the table the case can arise that the chunk
621 * to which we need to add is already full. In that case we have to
622 * allocate a new table and do something about that chunk. We have
623 * several strategies:
625 * If the number of elements in the table is below the low watermark
626 * or above the high watermark, we reallocate the whole table.
627 * Otherwise we only concern ourselves with the overflowing chunk:
629 * If there are no tombstones in the chunk then we split the chunk in
630 * two, each half full.
632 * If the chunk does contain tombstones, we just make a new copy of
633 * the chunk without the tombstones, which will have room for at least
634 * the one element we have to add.
636 static MonoJitInfoTable*
637 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
639 int num_elements = jit_info_table_num_elements (table);
642 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
643 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
644 //printf ("reallocing table\n");
645 return jit_info_table_realloc (table);
648 /* count the number of non-tombstone elements in the chunk */
650 for (i = 0; i < chunk->num_elements; ++i) {
651 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
655 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
656 //printf ("splitting chunk\n");
657 return jit_info_table_copy_and_split_chunk (table, chunk);
660 //printf ("purifying chunk\n");
661 return jit_info_table_copy_and_purify_chunk (table, chunk);
664 /* We add elements to the table by first making space for them by
665 * shifting the elements at the back to the right, one at a time.
666 * This results in duplicate entries during the process, but during
667 * all the time the table is in a sorted state. Also, when an element
668 * is replaced by another one, the element that replaces it has an end
669 * address that is equal to or lower than that of the replaced
670 * element. That property is necessary to guarantee that when
671 * searching for an element we end up at a position not higher than
672 * the one we're looking for (i.e. we either find the element directly
673 * or we end up to the left of it).
676 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
678 MonoJitInfoTable *table;
680 MonoJitInfoTableChunk *chunk;
684 g_assert (ji->method != NULL);
686 mono_domain_lock (domain);
688 ++mono_stats.jit_info_table_insert_count;
690 table = domain->jit_info_table;
693 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
694 g_assert (chunk_pos < table->num_chunks);
695 chunk = table->chunks [chunk_pos];
697 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
698 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
700 /* Debugging code, should be removed. */
701 //jit_info_table_check (new_table);
703 domain->jit_info_table = new_table;
704 mono_memory_barrier ();
705 domain->num_jit_info_tables++;
706 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free);
712 /* Debugging code, should be removed. */
713 //jit_info_table_check (table);
715 num_elements = chunk->num_elements;
717 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
719 /* First we need to size up the chunk by one, by copying the
720 last item, or inserting the first one, if the table is
722 if (num_elements > 0)
723 chunk->data [num_elements] = chunk->data [num_elements - 1];
725 chunk->data [0] = ji;
726 mono_memory_write_barrier ();
727 chunk->num_elements = ++num_elements;
729 /* Shift the elements up one by one. */
730 for (i = num_elements - 2; i >= pos; --i) {
731 mono_memory_write_barrier ();
732 chunk->data [i + 1] = chunk->data [i];
735 /* Now we have room and can insert the new item. */
736 mono_memory_write_barrier ();
737 chunk->data [pos] = ji;
739 /* Set the high code end address chunk entry. */
740 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
741 + chunk->data [chunk->num_elements - 1]->code_size;
743 /* Debugging code, should be removed. */
744 //jit_info_table_check (table);
746 mono_domain_unlock (domain);
750 mono_jit_info_make_tombstone (MonoJitInfo *ji)
752 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
754 tombstone->code_start = ji->code_start;
755 tombstone->code_size = ji->code_size;
756 tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
762 * LOCKING: domain lock
765 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
767 if (domain->num_jit_info_tables <= 1) {
768 /* Can it actually happen that we only have one table
769 but ji is still hazardous? */
770 mono_thread_hazardous_free_or_queue (ji, g_free);
772 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
777 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
779 MonoJitInfoTable *table;
780 MonoJitInfoTableChunk *chunk;
781 gpointer start = ji->code_start;
784 mono_domain_lock (domain);
785 table = domain->jit_info_table;
787 ++mono_stats.jit_info_table_remove_count;
789 chunk_pos = jit_info_table_index (table, start);
790 g_assert (chunk_pos < table->num_chunks);
792 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
795 chunk = table->chunks [chunk_pos];
797 while (pos < chunk->num_elements) {
798 if (chunk->data [pos] == ji)
801 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
802 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
803 <= (guint8*)ji->code_start + ji->code_size);
810 } while (chunk_pos < table->num_chunks);
813 g_assert (chunk->data [pos] == ji);
815 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
817 /* Debugging code, should be removed. */
818 //jit_info_table_check (table);
820 mono_jit_info_free_or_queue (domain, ji);
822 mono_domain_unlock (domain);
825 static MonoAotModuleInfoTable*
826 mono_aot_module_info_table_new (void)
828 return g_array_new (FALSE, FALSE, sizeof (gpointer));
832 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
834 int left = 0, right = table->len;
836 while (left < right) {
837 int pos = (left + right) / 2;
838 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
839 char *start = ainfo->start;
840 char *end = ainfo->end;
844 else if (addr >= end)
854 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
856 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
859 ainfo->image = image;
860 ainfo->start = start;
863 mono_appdomains_lock ();
866 aot_modules = mono_aot_module_info_table_new ();
868 pos = aot_info_table_index (aot_modules, start);
870 g_array_insert_val (aot_modules, pos, ainfo);
872 mono_appdomains_unlock ();
876 mono_jit_info_find_aot_module (guint8* addr)
878 guint left = 0, right;
883 mono_appdomains_lock ();
885 right = aot_modules->len;
886 while (left < right) {
887 guint pos = (left + right) / 2;
888 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
890 if (addr < (guint8*)ai->start)
892 else if (addr >= (guint8*)ai->end)
895 mono_appdomains_unlock ();
900 mono_appdomains_unlock ();
906 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
908 jit_info_find_in_aot_func = func;
912 mono_jit_info_get_code_start (MonoJitInfo* ji)
914 return ji->code_start;
918 mono_jit_info_get_code_size (MonoJitInfo* ji)
920 return ji->code_size;
924 mono_jit_info_get_method (MonoJitInfo* ji)
930 jit_info_key_extract (gpointer value)
932 MonoJitInfo *info = (MonoJitInfo*)value;
938 jit_info_next_value (gpointer value)
940 MonoJitInfo *info = (MonoJitInfo*)value;
942 return (gpointer*)&info->next_jit_code_hash;
946 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
948 mono_internal_hash_table_init (jit_code_hash,
949 mono_aligned_addr_hash,
950 jit_info_key_extract,
951 jit_info_next_value);
955 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
957 if (ji->has_generic_jit_info)
958 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
964 * mono_jit_info_get_generic_sharing_context:
967 * Returns the jit info's generic sharing context, or NULL if it
970 MonoGenericSharingContext*
971 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
973 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
976 return gi->generic_sharing_context;
982 * mono_jit_info_set_generic_sharing_context:
984 * @gsctx: a generic sharing context
986 * Sets the jit info's generic sharing context. The jit info must
987 * have memory allocated for the context.
990 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
992 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
996 gi->generic_sharing_context = gsctx;
1000 * mono_string_equal:
1001 * @s1: First string to compare
1002 * @s2: Second string to compare
1004 * Returns FALSE if the strings differ.
1007 mono_string_equal (MonoString *s1, MonoString *s2)
1009 int l1 = mono_string_length (s1);
1010 int l2 = mono_string_length (s2);
1017 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
1022 * @s: the string to hash
1024 * Returns the hash for the string.
1027 mono_string_hash (MonoString *s)
1029 const guint16 *p = mono_string_chars (s);
1030 int i, len = mono_string_length (s);
1033 for (i = 0; i < len; i++) {
1034 h = (h << 5) - h + *p;
1042 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1044 int len = GPOINTER_TO_INT (s1 [0]);
1045 if (len != GPOINTER_TO_INT (s2 [0]))
1048 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1052 mono_ptrarray_hash (gpointer *s)
1055 int len = GPOINTER_TO_INT (s [0]);
1058 for (i = 1; i < len; i++)
1059 hash += GPOINTER_TO_UINT (s [i]);
1065 * Allocate an id for domain and set domain->domain_id.
1066 * LOCKING: must be called while holding appdomains_mutex.
1067 * We try to assign low numbers to the domain, so it can be used
1068 * as an index in data tables to lookup domain-specific info
1069 * with minimal memory overhead. We also try not to reuse the
1070 * same id too quickly (to help debugging).
1073 domain_id_alloc (MonoDomain *domain)
1076 if (!appdomains_list) {
1077 appdomain_list_size = 2;
1078 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1080 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1081 if (!appdomains_list [i]) {
1087 for (i = 0; i < appdomain_next; ++i) {
1088 if (!appdomains_list [i]) {
1095 MonoDomain **new_list;
1096 int new_size = appdomain_list_size * 2;
1097 if (new_size >= (1 << 16))
1098 g_assert_not_reached ();
1099 id = appdomain_list_size;
1100 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1101 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1102 mono_gc_free_fixed (appdomains_list);
1103 appdomains_list = new_list;
1104 appdomain_list_size = new_size;
1106 domain->domain_id = id;
1107 appdomains_list [id] = domain;
1109 if (appdomain_next > appdomain_list_size)
1114 static guint32 domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1115 static gpointer domain_gc_desc = NULL;
1116 static guint32 domain_shadow_serial = 0L;
1119 mono_domain_create (void)
1122 guint32 shadow_serial;
1124 mono_appdomains_lock ();
1125 shadow_serial = domain_shadow_serial++;
1127 if (!domain_gc_desc) {
1128 unsigned int i, bit = 0;
1129 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1130 bit = i / sizeof (gpointer);
1131 domain_gc_bitmap [bit / 32] |= 1 << (bit % 32);
1133 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1135 mono_appdomains_unlock ();
1137 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1138 domain->shadow_serial = shadow_serial;
1139 domain->domain = NULL;
1140 domain->setup = NULL;
1141 domain->friendly_name = NULL;
1142 domain->search_path = NULL;
1144 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1146 domain->mp = mono_mempool_new ();
1147 domain->code_mp = mono_code_manager_new ();
1148 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1149 domain->domain_assemblies = NULL;
1150 domain->class_vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1151 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1152 domain->static_data_array = NULL;
1153 mono_jit_code_hash_init (&domain->jit_code_hash);
1154 domain->ldstr_table = mono_g_hash_table_new ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal);
1155 domain->num_jit_info_tables = 1;
1156 domain->jit_info_table = jit_info_table_new (domain);
1157 domain->jit_info_free_queue = NULL;
1158 domain->class_init_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1159 domain->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1160 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1161 domain->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1162 domain->delegate_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1164 InitializeCriticalSection (&domain->lock);
1165 InitializeCriticalSection (&domain->assemblies_lock);
1167 domain->shared_generics_hash = NULL;
1168 domain->method_rgctx_hash = NULL;
1170 mono_appdomains_lock ();
1171 domain_id_alloc (domain);
1172 mono_appdomains_unlock ();
1174 mono_debug_domain_create (domain);
1176 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1182 * mono_init_internal:
1184 * Creates the initial application domain and initializes the mono_defaults
1186 * This function is guaranteed to not run any IL code.
1187 * If exe_filename is not NULL, the method will determine the required runtime
1188 * from the exe configuration file or the version PE field.
1189 * If runtime_version is not NULL, that runtime version will be used.
1190 * Either exe_filename or runtime_version must be provided.
1192 * Returns: the initial domain.
1195 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1197 static MonoDomain *domain = NULL;
1198 MonoAssembly *ass = NULL;
1199 MonoImageOpenStatus status = MONO_IMAGE_OK;
1200 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1204 g_assert_not_reached ();
1206 #if defined(PLATFORM_WIN32) && !defined(_WIN64)
1207 mono_load_coree (exe_filename);
1210 mono_perfcounters_init ();
1212 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1213 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1214 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1216 mono_gc_base_init ();
1218 appdomain_thread_id = TlsAlloc ();
1220 InitializeCriticalSection (&appdomains_mutex);
1222 mono_metadata_init ();
1223 mono_raw_buffer_init ();
1224 mono_images_init ();
1225 mono_assemblies_init ();
1226 mono_classes_init ();
1227 mono_loader_init ();
1228 mono_reflection_init ();
1230 /* FIXME: When should we release this memory? */
1231 MONO_GC_REGISTER_ROOT (appdomains_list);
1233 domain = mono_domain_create ();
1234 mono_root_domain = domain;
1236 SET_APPDOMAIN (domain);
1238 /* Get a list of runtimes supported by the exe */
1239 if (exe_filename != NULL) {
1241 * This function will load the exe file as a MonoImage. We need to close it, but
1242 * that would mean it would be reloaded later. So instead, we save it to
1243 * exe_image, and close it during shutdown.
1245 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1246 #ifdef PLATFORM_WIN32
1248 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1250 exe_image = mono_image_open (exe_filename, NULL);
1252 mono_fixup_exe_image (exe_image);
1254 } else if (runtime_version != NULL) {
1255 runtimes [0] = get_runtime_by_version (runtime_version);
1256 runtimes [1] = NULL;
1259 if (runtimes [0] == NULL) {
1260 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1261 runtimes [0] = default_runtime;
1262 runtimes [1] = NULL;
1263 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1264 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1267 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1268 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1269 current_runtime = runtimes [n];
1270 ass = mono_assembly_load_corlib (current_runtime, &status);
1271 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1276 /* Now that we have a runtime, set the policy for unhandled exceptions */
1277 if (mono_get_runtime_info ()->framework_version [0] < '2') {
1278 mono_runtime_unhandled_exception_policy_set (MONO_UNHANLED_POLICY_LEGACY);
1281 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1283 case MONO_IMAGE_ERROR_ERRNO: {
1284 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1285 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1286 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1287 g_free (corlib_file);
1290 case MONO_IMAGE_IMAGE_INVALID:
1291 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1292 mono_assembly_getrootdir ());
1294 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1295 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1296 mono_assembly_getrootdir ());
1299 /* to suppress compiler warning */
1305 mono_defaults.corlib = mono_assembly_get_image (ass);
1307 mono_defaults.object_class = mono_class_from_name (
1308 mono_defaults.corlib, "System", "Object");
1309 g_assert (mono_defaults.object_class != 0);
1311 mono_defaults.void_class = mono_class_from_name (
1312 mono_defaults.corlib, "System", "Void");
1313 g_assert (mono_defaults.void_class != 0);
1315 mono_defaults.boolean_class = mono_class_from_name (
1316 mono_defaults.corlib, "System", "Boolean");
1317 g_assert (mono_defaults.boolean_class != 0);
1319 mono_defaults.byte_class = mono_class_from_name (
1320 mono_defaults.corlib, "System", "Byte");
1321 g_assert (mono_defaults.byte_class != 0);
1323 mono_defaults.sbyte_class = mono_class_from_name (
1324 mono_defaults.corlib, "System", "SByte");
1325 g_assert (mono_defaults.sbyte_class != 0);
1327 mono_defaults.int16_class = mono_class_from_name (
1328 mono_defaults.corlib, "System", "Int16");
1329 g_assert (mono_defaults.int16_class != 0);
1331 mono_defaults.uint16_class = mono_class_from_name (
1332 mono_defaults.corlib, "System", "UInt16");
1333 g_assert (mono_defaults.uint16_class != 0);
1335 mono_defaults.int32_class = mono_class_from_name (
1336 mono_defaults.corlib, "System", "Int32");
1337 g_assert (mono_defaults.int32_class != 0);
1339 mono_defaults.uint32_class = mono_class_from_name (
1340 mono_defaults.corlib, "System", "UInt32");
1341 g_assert (mono_defaults.uint32_class != 0);
1343 mono_defaults.uint_class = mono_class_from_name (
1344 mono_defaults.corlib, "System", "UIntPtr");
1345 g_assert (mono_defaults.uint_class != 0);
1347 mono_defaults.int_class = mono_class_from_name (
1348 mono_defaults.corlib, "System", "IntPtr");
1349 g_assert (mono_defaults.int_class != 0);
1351 mono_defaults.int64_class = mono_class_from_name (
1352 mono_defaults.corlib, "System", "Int64");
1353 g_assert (mono_defaults.int64_class != 0);
1355 mono_defaults.uint64_class = mono_class_from_name (
1356 mono_defaults.corlib, "System", "UInt64");
1357 g_assert (mono_defaults.uint64_class != 0);
1359 mono_defaults.single_class = mono_class_from_name (
1360 mono_defaults.corlib, "System", "Single");
1361 g_assert (mono_defaults.single_class != 0);
1363 mono_defaults.double_class = mono_class_from_name (
1364 mono_defaults.corlib, "System", "Double");
1365 g_assert (mono_defaults.double_class != 0);
1367 mono_defaults.char_class = mono_class_from_name (
1368 mono_defaults.corlib, "System", "Char");
1369 g_assert (mono_defaults.char_class != 0);
1371 mono_defaults.string_class = mono_class_from_name (
1372 mono_defaults.corlib, "System", "String");
1373 g_assert (mono_defaults.string_class != 0);
1375 mono_defaults.enum_class = mono_class_from_name (
1376 mono_defaults.corlib, "System", "Enum");
1377 g_assert (mono_defaults.enum_class != 0);
1379 mono_defaults.array_class = mono_class_from_name (
1380 mono_defaults.corlib, "System", "Array");
1381 g_assert (mono_defaults.array_class != 0);
1383 mono_defaults.delegate_class = mono_class_from_name (
1384 mono_defaults.corlib, "System", "Delegate");
1385 g_assert (mono_defaults.delegate_class != 0 );
1387 mono_defaults.multicastdelegate_class = mono_class_from_name (
1388 mono_defaults.corlib, "System", "MulticastDelegate");
1389 g_assert (mono_defaults.multicastdelegate_class != 0 );
1391 mono_defaults.asyncresult_class = mono_class_from_name (
1392 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1394 g_assert (mono_defaults.asyncresult_class != 0 );
1396 mono_defaults.waithandle_class = mono_class_from_name (
1397 mono_defaults.corlib, "System.Threading", "WaitHandle");
1398 g_assert (mono_defaults.waithandle_class != 0 );
1400 mono_defaults.typehandle_class = mono_class_from_name (
1401 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1402 g_assert (mono_defaults.typehandle_class != 0);
1404 mono_defaults.methodhandle_class = mono_class_from_name (
1405 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1406 g_assert (mono_defaults.methodhandle_class != 0);
1408 mono_defaults.fieldhandle_class = mono_class_from_name (
1409 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1410 g_assert (mono_defaults.fieldhandle_class != 0);
1412 mono_defaults.systemtype_class = mono_class_from_name (
1413 mono_defaults.corlib, "System", "Type");
1414 g_assert (mono_defaults.systemtype_class != 0);
1416 mono_defaults.monotype_class = mono_class_from_name (
1417 mono_defaults.corlib, "System", "MonoType");
1418 g_assert (mono_defaults.monotype_class != 0);
1420 mono_defaults.exception_class = mono_class_from_name (
1421 mono_defaults.corlib, "System", "Exception");
1422 g_assert (mono_defaults.exception_class != 0);
1424 mono_defaults.threadabortexception_class = mono_class_from_name (
1425 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1426 g_assert (mono_defaults.threadabortexception_class != 0);
1428 mono_defaults.thread_class = mono_class_from_name (
1429 mono_defaults.corlib, "System.Threading", "Thread");
1430 g_assert (mono_defaults.thread_class != 0);
1432 mono_defaults.appdomain_class = mono_class_from_name (
1433 mono_defaults.corlib, "System", "AppDomain");
1434 g_assert (mono_defaults.appdomain_class != 0);
1436 mono_defaults.transparent_proxy_class = mono_class_from_name (
1437 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1438 g_assert (mono_defaults.transparent_proxy_class != 0);
1440 mono_defaults.real_proxy_class = mono_class_from_name (
1441 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1442 g_assert (mono_defaults.real_proxy_class != 0);
1444 mono_defaults.mono_method_message_class = mono_class_from_name (
1445 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1446 g_assert (mono_defaults.mono_method_message_class != 0);
1448 mono_defaults.field_info_class = mono_class_from_name (
1449 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1450 g_assert (mono_defaults.field_info_class != 0);
1452 mono_defaults.method_info_class = mono_class_from_name (
1453 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1454 g_assert (mono_defaults.method_info_class != 0);
1456 mono_defaults.stringbuilder_class = mono_class_from_name (
1457 mono_defaults.corlib, "System.Text", "StringBuilder");
1458 g_assert (mono_defaults.stringbuilder_class != 0);
1460 mono_defaults.math_class = mono_class_from_name (
1461 mono_defaults.corlib, "System", "Math");
1462 g_assert (mono_defaults.math_class != 0);
1464 mono_defaults.stack_frame_class = mono_class_from_name (
1465 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1466 g_assert (mono_defaults.stack_frame_class != 0);
1468 mono_defaults.stack_trace_class = mono_class_from_name (
1469 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1470 g_assert (mono_defaults.stack_trace_class != 0);
1472 mono_defaults.marshal_class = mono_class_from_name (
1473 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1474 g_assert (mono_defaults.marshal_class != 0);
1476 mono_defaults.iserializeable_class = mono_class_from_name (
1477 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1478 g_assert (mono_defaults.iserializeable_class != 0);
1480 mono_defaults.serializationinfo_class = mono_class_from_name (
1481 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1482 g_assert (mono_defaults.serializationinfo_class != 0);
1484 mono_defaults.streamingcontext_class = mono_class_from_name (
1485 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1486 g_assert (mono_defaults.streamingcontext_class != 0);
1488 mono_defaults.typed_reference_class = mono_class_from_name (
1489 mono_defaults.corlib, "System", "TypedReference");
1490 g_assert (mono_defaults.typed_reference_class != 0);
1492 mono_defaults.argumenthandle_class = mono_class_from_name (
1493 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1494 g_assert (mono_defaults.argumenthandle_class != 0);
1496 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1497 mono_defaults.corlib, "System", "MarshalByRefObject");
1498 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1500 mono_defaults.monitor_class = mono_class_from_name (
1501 mono_defaults.corlib, "System.Threading", "Monitor");
1502 g_assert (mono_defaults.monitor_class != 0);
1504 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1505 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1506 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1508 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1509 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1511 mono_defaults.executioncontext_class = mono_class_from_name (
1512 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1514 mono_defaults.internals_visible_class = mono_class_from_name (
1515 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1518 * mscorlib needs a little help, only now it can load its friends list (after we have
1519 * loaded the InternalsVisibleToAttribute), load it now
1521 mono_assembly_load_friends (ass);
1523 mono_defaults.safehandle_class = mono_class_from_name (
1524 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1526 mono_defaults.handleref_class = mono_class_from_name (
1527 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1529 mono_defaults.attribute_class = mono_class_from_name (
1530 mono_defaults.corlib, "System", "Attribute");
1532 mono_defaults.customattribute_data_class = mono_class_from_name (
1533 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1535 /* these are initialized lazily when COM features are used */
1536 mono_defaults.variant_class = NULL;
1537 mono_defaults.com_object_class = NULL;
1538 mono_defaults.com_interop_proxy_class = NULL;
1539 mono_defaults.iunknown_class = NULL;
1540 mono_defaults.idispatch_class = NULL;
1543 * Note that mono_defaults.generic_*_class is only non-NULL if we're
1544 * using the 2.0 corlib.
1546 mono_class_init (mono_defaults.array_class);
1547 mono_defaults.generic_nullable_class = mono_class_from_name (
1548 mono_defaults.corlib, "System", "Nullable`1");
1549 mono_defaults.generic_ilist_class = mono_class_from_name (
1550 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1552 domain->friendly_name = g_path_get_basename (filename);
1554 _mono_debug_init_corlib (domain);
1562 * Creates the initial application domain and initializes the mono_defaults
1564 * This function is guaranteed to not run any IL code.
1565 * The runtime is initialized using the default runtime version.
1567 * Returns: the initial domain.
1570 mono_init (const char *domain_name)
1572 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1576 * mono_init_from_assembly:
1578 * Creates the initial application domain and initializes the mono_defaults
1580 * This function is guaranteed to not run any IL code.
1581 * The runtime is initialized using the runtime version required by the
1582 * provided executable. The version is determined by looking at the exe
1583 * configuration file and the version PE field)
1585 * Returns: the initial domain.
1588 mono_init_from_assembly (const char *domain_name, const char *filename)
1590 return mono_init_internal (domain_name, filename, NULL);
1594 * mono_init_version:
1596 * Creates the initial application domain and initializes the mono_defaults
1598 * This function is guaranteed to not run any IL code.
1599 * The runtime is initialized using the provided rutime version.
1601 * Returns: the initial domain.
1604 mono_init_version (const char *domain_name, const char *version)
1606 return mono_init_internal (domain_name, NULL, version);
1610 * mono_init_com_types:
1612 * Initializes all types needed for COM Interop in mono_defaults structure.
1615 mono_init_com_types (void)
1617 static gboolean initialized = FALSE;
1622 /* FIXME: do I need some threading protection here */
1624 g_assert (mono_defaults.corlib);
1626 mono_defaults.variant_class = mono_class_from_name (
1627 mono_defaults.corlib, "System", "Variant");
1628 g_assert (mono_defaults.variant_class != 0);
1630 mono_defaults.com_object_class = mono_class_from_name (
1631 mono_defaults.corlib, "System", "__ComObject");
1632 g_assert (mono_defaults.com_object_class != 0);
1634 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1635 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1636 g_assert (mono_defaults.com_interop_proxy_class != 0);
1638 mono_defaults.iunknown_class = mono_class_from_name (
1639 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1640 g_assert (mono_defaults.iunknown_class != 0);
1642 mono_defaults.idispatch_class = mono_class_from_name (
1643 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1644 g_assert (mono_defaults.idispatch_class != 0);
1652 * Cleans up all metadata modules.
1657 mono_close_exe_image ();
1659 mono_loader_cleanup ();
1660 mono_classes_cleanup ();
1661 mono_assemblies_cleanup ();
1662 mono_images_cleanup ();
1663 mono_debug_cleanup ();
1664 mono_raw_buffer_cleanup ();
1665 mono_metadata_cleanup ();
1667 TlsFree (appdomain_thread_id);
1668 DeleteCriticalSection (&appdomains_mutex);
1672 mono_close_exe_image (void)
1675 mono_image_close (exe_image);
1679 * mono_get_root_domain:
1681 * The root AppDomain is the initial domain created by the runtime when it is
1682 * initialized. Programs execute on this AppDomain, but can create new ones
1683 * later. Currently there is no unmanaged API to create new AppDomains, this
1684 * must be done from managed code.
1686 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1689 mono_get_root_domain (void)
1691 return mono_root_domain;
1697 * Returns: the current domain, to obtain the root domain use
1698 * mono_get_root_domain().
1703 return GET_APPDOMAIN ();
1707 * mono_domain_set_internal:
1708 * @domain: the new domain
1710 * Sets the current domain to @domain.
1713 mono_domain_set_internal (MonoDomain *domain)
1715 SET_APPDOMAIN (domain);
1716 SET_APPCONTEXT (domain->default_context);
1720 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1726 * Create a copy of the data to avoid calling the user callback
1727 * inside the lock because that could lead to deadlocks.
1728 * We can do this because this function is not perf. critical.
1730 mono_appdomains_lock ();
1731 size = appdomain_list_size;
1732 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1733 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1734 mono_appdomains_unlock ();
1736 for (i = 0; i < size; ++i) {
1738 func (copy [i], user_data);
1741 mono_gc_free_fixed (copy);
1745 * mono_domain_assembly_open:
1746 * @domain: the application domain
1747 * @name: file name of the assembly
1749 * fixme: maybe we should integrate this with mono_assembly_open ??
1752 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1757 mono_domain_assemblies_lock (domain);
1758 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1760 if (strcmp (name, ass->aname.name) == 0) {
1761 mono_domain_assemblies_unlock (domain);
1765 mono_domain_assemblies_unlock (domain);
1767 if (!(ass = mono_assembly_open (name, NULL)))
1774 mono_domain_lookup_shared_generic (MonoDomain *domain, MonoMethod *method)
1776 if (!domain->shared_generics_hash)
1779 return g_hash_table_lookup (domain->shared_generics_hash, method);
1783 mono_domain_register_shared_generic (MonoDomain *domain, MonoMethod *method, MonoJitInfo *jit_info)
1785 if (!domain->shared_generics_hash)
1786 domain->shared_generics_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1788 g_assert (domain->shared_generics_hash);
1790 g_hash_table_insert (domain->shared_generics_hash, method, jit_info);
1794 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
1796 MonoJitDynamicMethodInfo *di = value;
1797 mono_code_manager_destroy (di->code_mp);
1802 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
1804 g_slist_free (value);
1808 mono_domain_free (MonoDomain *domain, gboolean force)
1810 int code_size, code_alloc;
1812 if ((domain == mono_root_domain) && !force) {
1813 g_warning ("cant unload root domain");
1817 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1819 mono_debug_domain_unload (domain);
1821 mono_appdomains_lock ();
1822 appdomains_list [domain->domain_id] = NULL;
1823 mono_appdomains_unlock ();
1825 /* FIXME: free delegate_hash_table when it's used */
1826 if (domain->search_path) {
1827 g_strfreev (domain->search_path);
1828 domain->search_path = NULL;
1830 domain->create_proxy_for_type_method = NULL;
1831 domain->private_invoke_method = NULL;
1832 domain->default_context = NULL;
1833 domain->out_of_memory_ex = NULL;
1834 domain->null_reference_ex = NULL;
1835 domain->stack_overflow_ex = NULL;
1836 domain->entry_assembly = NULL;
1837 /* must do this early as it accesses fields and types */
1838 if (domain->special_static_fields) {
1839 mono_alloc_special_static_data_free (domain->special_static_fields);
1840 g_hash_table_destroy (domain->special_static_fields);
1841 domain->special_static_fields = NULL;
1843 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1844 MonoAssembly *ass = tmp->data;
1845 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);
1846 mono_assembly_close (ass);
1848 g_slist_free (domain->domain_assemblies);
1849 domain->domain_assemblies = NULL;
1851 g_free (domain->friendly_name);
1852 domain->friendly_name = NULL;
1853 mono_g_hash_table_destroy (domain->env);
1855 g_hash_table_destroy (domain->class_vtable_hash);
1856 domain->class_vtable_hash = NULL;
1857 g_hash_table_destroy (domain->proxy_vtable_hash);
1858 domain->proxy_vtable_hash = NULL;
1859 if (domain->static_data_array) {
1860 mono_gc_free_fixed (domain->static_data_array);
1861 domain->static_data_array = NULL;
1863 mono_internal_hash_table_destroy (&domain->jit_code_hash);
1864 if (domain->dynamic_code_hash) {
1865 g_hash_table_foreach (domain->dynamic_code_hash, dynamic_method_info_free, NULL);
1866 g_hash_table_destroy (domain->dynamic_code_hash);
1867 domain->dynamic_code_hash = NULL;
1869 mono_g_hash_table_destroy (domain->ldstr_table);
1870 domain->ldstr_table = NULL;
1873 * There might still be jit info tables of this domain which
1874 * are not freed. Since the domain cannot be in use anymore,
1875 * this will free them.
1877 mono_thread_hazardous_try_free_all ();
1878 g_assert (domain->num_jit_info_tables == 1);
1879 jit_info_table_free (domain->jit_info_table);
1880 domain->jit_info_table = NULL;
1881 g_assert (!domain->jit_info_free_queue);
1883 /* collect statistics */
1884 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
1885 total_domain_code_alloc += code_alloc;
1886 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
1887 max_domain_code_size = MAX (max_domain_code_size, code_size);
1889 #ifdef DEBUG_DOMAIN_UNLOAD
1890 mono_mempool_invalidate (domain->mp);
1891 mono_code_manager_invalidate (domain->code_mp);
1893 mono_mempool_destroy (domain->mp);
1895 mono_code_manager_destroy (domain->code_mp);
1896 domain->code_mp = NULL;
1898 if (domain->jump_target_hash) {
1899 g_hash_table_foreach (domain->jump_target_hash, delete_jump_list, NULL);
1900 g_hash_table_destroy (domain->jump_target_hash);
1901 domain->jump_target_hash = NULL;
1903 if (domain->type_hash) {
1904 mono_g_hash_table_destroy (domain->type_hash);
1905 domain->type_hash = NULL;
1907 if (domain->refobject_hash) {
1908 mono_g_hash_table_destroy (domain->refobject_hash);
1909 domain->refobject_hash = NULL;
1911 if (domain->type_init_exception_hash) {
1912 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1913 domain->type_init_exception_hash = NULL;
1915 g_hash_table_destroy (domain->class_init_trampoline_hash);
1916 domain->class_init_trampoline_hash = NULL;
1917 g_hash_table_destroy (domain->jump_trampoline_hash);
1918 domain->jump_trampoline_hash = NULL;
1919 g_hash_table_destroy (domain->finalizable_objects_hash);
1920 domain->finalizable_objects_hash = NULL;
1921 g_hash_table_destroy (domain->jit_trampoline_hash);
1922 domain->jit_trampoline_hash = NULL;
1923 g_hash_table_destroy (domain->delegate_trampoline_hash);
1924 domain->delegate_trampoline_hash = NULL;
1925 if (domain->shared_generics_hash) {
1926 g_hash_table_destroy (domain->shared_generics_hash);
1927 domain->shared_generics_hash = NULL;
1929 if (domain->method_rgctx_hash) {
1930 g_hash_table_destroy (domain->method_rgctx_hash);
1931 domain->method_rgctx_hash = NULL;
1934 DeleteCriticalSection (&domain->assemblies_lock);
1935 DeleteCriticalSection (&domain->lock);
1936 domain->setup = NULL;
1938 /* FIXME: anything else required ? */
1940 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
1942 mono_gc_free_fixed (domain);
1944 if ((domain == mono_root_domain))
1945 mono_root_domain = NULL;
1949 * mono_domain_get_id:
1952 * Returns: the a domain for a specific domain id.
1955 mono_domain_get_by_id (gint32 domainid)
1957 MonoDomain * domain;
1959 mono_appdomains_lock ();
1960 if (domainid < appdomain_list_size)
1961 domain = appdomains_list [domainid];
1964 mono_appdomains_unlock ();
1970 mono_domain_get_id (MonoDomain *domain)
1972 return domain->domain_id;
1976 mono_context_set (MonoAppContext * new_context)
1978 SET_APPCONTEXT (new_context);
1982 mono_context_get (void)
1984 return GET_APPCONTEXT ();
1987 /* LOCKING: the caller holds the lock for this domain */
1989 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
1991 /* The first entry in the array is the index of the next free slot
1992 * and the total size of the array
1995 if (domain->static_data_array) {
1996 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
1997 next = GPOINTER_TO_INT (domain->static_data_array [0]);
1999 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), NULL);
2000 memcpy (new_array, domain->static_data_array, sizeof (gpointer) * size);
2002 new_array [1] = GINT_TO_POINTER (size);
2003 mono_gc_free_fixed (domain->static_data_array);
2004 domain->static_data_array = new_array;
2008 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, NULL);
2010 new_array [0] = GINT_TO_POINTER (next);
2011 new_array [1] = GINT_TO_POINTER (size);
2012 domain->static_data_array = new_array;
2014 domain->static_data_array [next++] = data;
2015 domain->static_data_array [0] = GINT_TO_POINTER (next);
2019 mono_get_corlib (void)
2021 return mono_defaults.corlib;
2025 mono_get_object_class (void)
2027 return mono_defaults.object_class;
2031 mono_get_byte_class (void)
2033 return mono_defaults.byte_class;
2037 mono_get_void_class (void)
2039 return mono_defaults.void_class;
2043 mono_get_boolean_class (void)
2045 return mono_defaults.boolean_class;
2049 mono_get_sbyte_class (void)
2051 return mono_defaults.sbyte_class;
2055 mono_get_int16_class (void)
2057 return mono_defaults.int16_class;
2061 mono_get_uint16_class (void)
2063 return mono_defaults.uint16_class;
2067 mono_get_int32_class (void)
2069 return mono_defaults.int32_class;
2073 mono_get_uint32_class (void)
2075 return mono_defaults.uint32_class;
2079 mono_get_intptr_class (void)
2081 return mono_defaults.int_class;
2085 mono_get_uintptr_class (void)
2087 return mono_defaults.uint_class;
2091 mono_get_int64_class (void)
2093 return mono_defaults.int64_class;
2097 mono_get_uint64_class (void)
2099 return mono_defaults.uint64_class;
2103 mono_get_single_class (void)
2105 return mono_defaults.single_class;
2109 mono_get_double_class (void)
2111 return mono_defaults.double_class;
2115 mono_get_char_class (void)
2117 return mono_defaults.char_class;
2121 mono_get_string_class (void)
2123 return mono_defaults.string_class;
2127 mono_get_enum_class (void)
2129 return mono_defaults.enum_class;
2133 mono_get_array_class (void)
2135 return mono_defaults.array_class;
2139 mono_get_thread_class (void)
2141 return mono_defaults.thread_class;
2145 mono_get_exception_class (void)
2147 return mono_defaults.exception_class;
2151 static char* get_attribute_value (const gchar **attribute_names,
2152 const gchar **attribute_values,
2153 const char *att_name)
2156 for (n=0; attribute_names[n] != NULL; n++) {
2157 if (strcmp (attribute_names[n], att_name) == 0)
2158 return g_strdup (attribute_values[n]);
2163 static void start_element (GMarkupParseContext *context,
2164 const gchar *element_name,
2165 const gchar **attribute_names,
2166 const gchar **attribute_values,
2170 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2172 if (strcmp (element_name, "configuration") == 0) {
2173 app_config->configuration_count++;
2176 if (strcmp (element_name, "startup") == 0) {
2177 app_config->startup_count++;
2181 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2184 if (strcmp (element_name, "requiredRuntime") == 0) {
2185 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2186 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2187 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2188 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2192 static void end_element (GMarkupParseContext *context,
2193 const gchar *element_name,
2197 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2199 if (strcmp (element_name, "configuration") == 0) {
2200 app_config->configuration_count--;
2201 } else if (strcmp (element_name, "startup") == 0) {
2202 app_config->startup_count--;
2206 static const GMarkupParser
2215 static AppConfigInfo *
2216 app_config_parse (const char *exe_filename)
2218 AppConfigInfo *app_config;
2219 GMarkupParseContext *context;
2223 const char *bundled_config;
2224 char *config_filename;
2226 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2228 if (bundled_config) {
2229 text = g_strdup (bundled_config);
2230 len = strlen (text);
2232 config_filename = g_strconcat (exe_filename, ".config", NULL);
2234 if (stat (config_filename, &buf) != 0) {
2235 g_free (config_filename);
2239 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2240 g_free (config_filename);
2243 g_free (config_filename);
2246 app_config = g_new0 (AppConfigInfo, 1);
2248 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2249 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2250 g_markup_parse_context_end_parse (context, NULL);
2252 g_markup_parse_context_free (context);
2258 app_config_free (AppConfigInfo* app_config)
2261 GSList *list = app_config->supported_runtimes;
2262 while (list != NULL) {
2263 rt = (char*)list->data;
2265 list = g_slist_next (list);
2267 g_slist_free (app_config->supported_runtimes);
2268 g_free (app_config->required_runtime);
2269 g_free (app_config);
2273 static const MonoRuntimeInfo*
2274 get_runtime_by_version (const char *version)
2277 int max = G_N_ELEMENTS (supported_runtimes);
2279 for (n=0; n<max; n++) {
2280 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2281 return &supported_runtimes[n];
2287 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2289 AppConfigInfo* app_config;
2291 const MonoRuntimeInfo* runtime = NULL;
2292 MonoImage *image = NULL;
2294 app_config = app_config_parse (exe_file);
2296 if (app_config != NULL) {
2297 /* Check supportedRuntime elements, if none is supported, fail.
2298 * If there are no such elements, look for a requiredRuntime element.
2300 if (app_config->supported_runtimes != NULL) {
2302 GSList *list = app_config->supported_runtimes;
2303 while (list != NULL) {
2304 version = (char*) list->data;
2305 runtime = get_runtime_by_version (version);
2306 if (runtime != NULL)
2307 runtimes [n++] = runtime;
2308 list = g_slist_next (list);
2310 runtimes [n] = NULL;
2311 app_config_free (app_config);
2315 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2316 if (app_config->required_runtime != NULL) {
2317 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2318 runtimes [1] = NULL;
2319 app_config_free (app_config);
2322 app_config_free (app_config);
2325 /* Look for a runtime with the exact version */
2326 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2329 image = mono_image_open (exe_file, NULL);
2331 if (image == NULL) {
2332 /* The image is wrong or the file was not found. In this case return
2333 * a default runtime and leave to the initialization method the work of
2334 * reporting the error.
2336 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2337 runtimes [1] = NULL;
2343 runtimes [0] = get_runtime_by_version (image->version);
2344 runtimes [1] = NULL;
2349 * mono_get_runtime_info:
2351 * Returns: the version of the current runtime instance.
2353 const MonoRuntimeInfo*
2354 mono_get_runtime_info (void)
2356 return current_runtime;
2360 mono_debugger_check_runtime_version (const char *filename)
2362 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2363 const MonoRuntimeInfo *rinfo;
2366 get_runtimes_from_exe (filename, &image, runtimes);
2367 rinfo = runtimes [0];
2370 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2372 if (rinfo != current_runtime)
2373 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2374 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2375 filename, rinfo->runtime_version);