2 * domain.c: MonoDomain functions
5 * Dietmar Maurer (dietmar@ximian.com)
8 * (C) 2001 Ximian, Inc.
16 #include <mono/os/gc_wrapper.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/metadata/object.h>
22 #include <mono/metadata/object-internals.h>
23 #include <mono/metadata/domain-internals.h>
24 #include <mono/metadata/class-internals.h>
25 #include <mono/metadata/assembly.h>
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/cil-coff.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>
37 /* #define DEBUG_DOMAIN_UNLOAD */
39 /* we need to use both the Tls* functions and __thread because
40 * some archs may generate faster jit code with one meachanism
41 * or the other (we used to do it because tls slots were GC-tracked,
42 * but we can't depend on this).
44 static guint32 appdomain_thread_id = -1;
47 static __thread MonoDomain * tls_appdomain MONO_TLS_FAST;
48 #define GET_APPDOMAIN() tls_appdomain
49 #define SET_APPDOMAIN(x) do { \
51 TlsSetValue (appdomain_thread_id, x); \
56 #define GET_APPDOMAIN() ((MonoDomain *)TlsGetValue (appdomain_thread_id))
57 #define SET_APPDOMAIN(x) TlsSetValue (appdomain_thread_id, x);
61 #define GET_APPCONTEXT() (mono_thread_current ()->current_appcontext)
62 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_current (), current_appcontext, (x))
64 static guint16 appdomain_list_size = 0;
65 static guint16 appdomain_next = 0;
66 static MonoDomain **appdomains_list = NULL;
68 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
69 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
70 static CRITICAL_SECTION appdomains_mutex;
72 static MonoDomain *mono_root_domain = NULL;
74 /* AppConfigInfo: Information about runtime versions supported by an
78 GSList *supported_runtimes;
79 char *required_runtime;
80 int configuration_count;
85 * AotModuleInfo: Contains information about AOT modules.
92 static const MonoRuntimeInfo *current_runtime = NULL;
94 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
97 * Contains information about AOT loaded code.
99 static MonoAotModuleInfoTable *aot_modules = NULL;
101 /* This is the list of runtime versions supported by this JIT.
103 static const MonoRuntimeInfo supported_runtimes[] = {
104 {"v1.0.3705", "1.0", { {1,0,5000,0}, {7,0,5000,0} } },
105 {"v1.1.4322", "1.0", { {1,0,5000,0}, {7,0,5000,0} } },
106 {"v2.0.50215","2.0", { {2,0,0,0}, {8,0,0,0} } },
107 {"v2.0.50727","2.0", { {2,0,0,0}, {8,0,0,0} } },
108 {"moonlight", "2.1", { {2,1,0,0}, {9,0,0,0} } },
112 /* The stable runtime version */
113 #define DEFAULT_RUNTIME_VERSION "v1.1.4322"
116 get_runtimes_from_exe (const char *exe_file, const MonoRuntimeInfo** runtimes);
118 static const MonoRuntimeInfo*
119 get_runtime_by_version (const char *version);
122 mono_jit_info_find_aot_module (guint8* addr);
125 mono_domain_get_tls_key (void)
127 return appdomain_thread_id;
131 mono_domain_get_tls_offset (void)
134 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
135 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
140 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
141 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
142 #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)
144 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
145 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
147 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == NULL)
149 #define JIT_INFO_TABLE_HAZARD_INDEX 0
150 #define JIT_INFO_HAZARD_INDEX 1
153 jit_info_table_num_elements (MonoJitInfoTable *table)
156 int num_elements = 0;
158 for (i = 0; i < table->num_chunks; ++i) {
159 MonoJitInfoTableChunk *chunk = table->chunks [i];
160 int chunk_num_elements = chunk->num_elements;
163 for (j = 0; j < chunk_num_elements; ++j) {
164 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
172 static MonoJitInfoTableChunk*
173 jit_info_table_new_chunk (void)
175 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
181 static MonoJitInfoTable *
182 jit_info_table_new (void)
184 MonoJitInfoTable *table = g_malloc0 (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*));
186 table->num_chunks = 1;
187 table->chunks [0] = jit_info_table_new_chunk ();
193 jit_info_table_free (MonoJitInfoTable *table)
196 int num_chunks = table->num_chunks;
198 /* At this point we assume that there are no other threads
199 still accessing the table, so we don't have to worry about
200 hazardous pointers. */
202 for (i = 0; i < num_chunks; ++i) {
203 MonoJitInfoTableChunk *chunk = table->chunks [i];
207 if (--chunk->refcount > 0)
210 num_elements = chunk->num_elements;
211 for (j = 0; j < num_elements; ++j) {
212 MonoJitInfo *ji = chunk->data [j];
214 if (IS_JIT_INFO_TOMBSTONE (ji))
224 /* Can be called with hp==NULL, in which case it acts as an ordinary
225 pointer fetch. It's used that way indirectly from
226 mono_jit_info_table_add(), which doesn't have to care about hazards
227 because it holds the respective domain lock. */
229 get_hazardous_pointer (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index)
234 /* Get the pointer */
236 /* If we don't have hazard pointers just return the
240 /* Make it hazardous */
241 mono_hazard_pointer_set (hp, hazard_index, p);
242 /* Check that it's still the same. If not, try
245 mono_hazard_pointer_clear (hp, hazard_index);
254 /* The jit_info_table is sorted in ascending order by the end
255 * addresses of the compiled methods. The reason why we have to do
256 * this is that once we introduce tombstones, it becomes possible for
257 * code ranges to overlap, and if we sort by code start and insert at
258 * the back of the table, we cannot guarantee that we won't overlook
261 * There are actually two possible ways to do the sorting and
262 * inserting which work with our lock-free mechanism:
264 * 1. Sort by start address and insert at the front. When looking for
265 * an entry, find the last one with a start address lower than the one
266 * you're looking for, then work your way to the front of the table.
268 * 2. Sort by end address and insert at the back. When looking for an
269 * entry, find the first one with an end address higher than the one
270 * you're looking for, then work your way to the end of the table.
272 * We chose the latter out of convenience.
275 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
277 int left = 0, right = table->num_chunks;
279 g_assert (left < right);
282 int pos = (left + right) / 2;
283 MonoJitInfoTableChunk *chunk = table->chunks [pos];
285 if (addr < chunk->last_code_end)
289 } while (left < right);
290 g_assert (left == right);
292 if (left >= table->num_chunks)
293 return table->num_chunks - 1;
298 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
300 int left = 0, right = chunk->num_elements;
302 while (left < right) {
303 int pos = (left + right) / 2;
304 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
305 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
312 g_assert (left == right);
318 mono_jit_info_table_find (MonoDomain *domain, char *addr)
320 MonoJitInfoTable *table;
323 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
325 ++mono_stats.jit_info_table_lookup_count;
327 /* First we have to get the domain's jit_info_table. This is
328 complicated by the fact that a writer might substitute a
329 new table and free the old one. What the writer guarantees
330 us is that it looks at the hazard pointers after it has
331 changed the jit_info_table pointer. So, if we guard the
332 table by a hazard pointer and make sure that the pointer is
333 still there after we've made it hazardous, we don't have to
334 worry about the writer freeing the table. */
335 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
337 chunk_pos = jit_info_table_index (table, (gint8*)addr);
338 g_assert (chunk_pos < table->num_chunks);
340 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
342 /* We now have a position that's very close to that of the
343 first element whose end address is higher than the one
344 we're looking for. If we don't have the exact position,
345 then we have a position below that one, so we'll just
346 search upward until we find our element. */
348 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
350 while (pos < chunk->num_elements) {
351 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
355 if (IS_JIT_INFO_TOMBSTONE (ji)) {
356 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
359 if ((gint8*)addr >= (gint8*)ji->code_start
360 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
361 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
362 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
366 /* If we find a non-tombstone element which is already
367 beyond what we're looking for, we have to end the
369 if ((gint8*)addr < (gint8*)ji->code_start)
375 } while (chunk_pos < table->num_chunks);
377 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
378 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
380 /* maybe it is shared code, so we also search in the root domain */
382 if (domain != mono_root_domain)
383 ji = mono_jit_info_table_find (mono_root_domain, addr);
386 /* Maybe its an AOT module */
387 MonoImage *image = mono_jit_info_find_aot_module ((guint8*)addr);
389 ji = jit_info_find_in_aot_func (domain, image, addr);
396 jit_info_table_check (MonoJitInfoTable *table)
400 for (i = 0; i < table->num_chunks; ++i) {
401 MonoJitInfoTableChunk *chunk = table->chunks [i];
404 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
405 if (chunk->refcount > 10)
406 printf("warning: chunk refcount is %d\n", chunk->refcount);
407 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
409 for (j = 0; j < chunk->num_elements; ++j) {
410 MonoJitInfo *this = chunk->data [j];
413 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
415 if (j < chunk->num_elements - 1)
416 next = chunk->data [j + 1];
417 else if (i < table->num_chunks - 1) {
420 for (k = i + 1; k < table->num_chunks; ++k)
421 if (table->chunks [k]->num_elements > 0)
424 if (k >= table->num_chunks)
427 g_assert (table->chunks [k]->num_elements > 0);
428 next = table->chunks [k]->data [0];
432 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
437 static MonoJitInfoTable*
438 jit_info_table_realloc (MonoJitInfoTable *old)
441 int num_elements = jit_info_table_num_elements (old);
444 int new_chunk, new_element;
445 MonoJitInfoTable *new;
447 /* number of needed places for elements needed */
448 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
449 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
451 new = g_malloc (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*) * num_chunks);
452 new->num_chunks = num_chunks;
454 for (i = 0; i < num_chunks; ++i)
455 new->chunks [i] = jit_info_table_new_chunk ();
459 for (i = 0; i < old->num_chunks; ++i) {
460 MonoJitInfoTableChunk *chunk = old->chunks [i];
461 int chunk_num_elements = chunk->num_elements;
464 for (j = 0; j < chunk_num_elements; ++j) {
465 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
466 g_assert (new_chunk < num_chunks);
467 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
468 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
469 new->chunks [new_chunk]->num_elements = new_element;
477 if (new_chunk < num_chunks) {
478 g_assert (new_chunk == num_chunks - 1);
479 new->chunks [new_chunk]->num_elements = new_element;
480 g_assert (new->chunks [new_chunk]->num_elements > 0);
483 for (i = 0; i < num_chunks; ++i) {
484 MonoJitInfoTableChunk *chunk = new->chunks [i];
485 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
487 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
494 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
496 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
497 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
499 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
501 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
502 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
504 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
505 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
507 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
508 + new1->data [new1->num_elements - 1]->code_size;
509 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
510 + new2->data [new2->num_elements - 1]->code_size;
516 static MonoJitInfoTable*
517 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
519 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
520 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
523 new_table->num_chunks = table->num_chunks + 1;
526 for (i = 0; i < table->num_chunks; ++i) {
527 if (table->chunks [i] == chunk) {
528 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
531 new_table->chunks [j] = table->chunks [i];
532 ++new_table->chunks [j]->refcount;
537 g_assert (j == new_table->num_chunks);
542 static MonoJitInfoTableChunk*
543 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
545 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
549 for (i = 0; i < old->num_elements; ++i) {
550 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
551 new->data [j++] = old->data [i];
554 new->num_elements = j;
555 if (new->num_elements > 0)
556 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
558 new->last_code_end = old->last_code_end;
563 static MonoJitInfoTable*
564 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
566 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
567 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
570 new_table->num_chunks = table->num_chunks;
573 for (i = 0; i < table->num_chunks; ++i) {
574 if (table->chunks [i] == chunk)
575 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
577 new_table->chunks [j] = table->chunks [i];
578 ++new_table->chunks [j]->refcount;
583 g_assert (j == new_table->num_chunks);
588 /* As we add an element to the table the case can arise that the chunk
589 * to which we need to add is already full. In that case we have to
590 * allocate a new table and do something about that chunk. We have
591 * several strategies:
593 * If the number of elements in the table is below the low watermark
594 * or above the high watermark, we reallocate the whole table.
595 * Otherwise we only concern ourselves with the overflowing chunk:
597 * If there are no tombstones in the chunk then we split the chunk in
598 * two, each half full.
600 * If the chunk does contain tombstones, we just make a new copy of
601 * the chunk without the tombstones, which will have room for at least
602 * the one element we have to add.
604 static MonoJitInfoTable*
605 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
607 int num_elements = jit_info_table_num_elements (table);
610 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
611 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
612 //printf ("reallocing table\n");
613 return jit_info_table_realloc (table);
616 /* count the number of non-tombstone elements in the chunk */
618 for (i = 0; i < chunk->num_elements; ++i) {
619 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
623 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
624 //printf ("splitting chunk\n");
625 return jit_info_table_copy_and_split_chunk (table, chunk);
628 //printf ("purifying chunk\n");
629 return jit_info_table_copy_and_purify_chunk (table, chunk);
632 /* We add elements to the table by first making space for them by
633 * shifting the elements at the back to the right, one at a time.
634 * This results in duplicate entries during the process, but during
635 * all the time the table is in a sorted state. Also, when an element
636 * is replaced by another one, the element that replaces it has an end
637 * address that is equal to or lower than that of the replaced
638 * element. That property is necessary to guarantee that when
639 * searching for an element we end up at a position not higher than
640 * the one we're looking for (i.e. we either find the element directly
641 * or we end up to the left of it).
644 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
646 MonoJitInfoTable *table;
648 MonoJitInfoTableChunk *chunk;
652 g_assert (ji->method != NULL);
654 mono_domain_lock (domain);
656 ++mono_stats.jit_info_table_insert_count;
658 table = domain->jit_info_table;
661 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
662 g_assert (chunk_pos < table->num_chunks);
663 chunk = table->chunks [chunk_pos];
665 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
666 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
668 /* Debugging code, should be removed. */
669 //jit_info_table_check (new_table);
671 domain->jit_info_table = new_table;
672 mono_memory_barrier ();
673 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free);
679 /* Debugging code, should be removed. */
680 //jit_info_table_check (table);
682 num_elements = chunk->num_elements;
684 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
686 /* First we need to size up the chunk by one, by copying the
687 last item, or inserting the first one, if the table is
689 if (num_elements > 0)
690 chunk->data [num_elements] = chunk->data [num_elements - 1];
692 chunk->data [0] = ji;
693 mono_memory_write_barrier ();
694 chunk->num_elements = ++num_elements;
696 /* Shift the elements up one by one. */
697 for (i = num_elements - 2; i >= pos; --i) {
698 mono_memory_write_barrier ();
699 chunk->data [i + 1] = chunk->data [i];
702 /* Now we have room and can insert the new item. */
703 mono_memory_write_barrier ();
704 chunk->data [pos] = ji;
706 /* Set the high code end address chunk entry. */
707 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
708 + chunk->data [chunk->num_elements - 1]->code_size;
710 /* Debugging code, should be removed. */
711 //jit_info_table_check (table);
713 mono_domain_unlock (domain);
717 mono_jit_info_make_tombstone (MonoJitInfo *ji)
719 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
721 tombstone->code_start = ji->code_start;
722 tombstone->code_size = ji->code_size;
723 tombstone->method = NULL;
729 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
731 MonoJitInfoTable *table;
732 MonoJitInfoTableChunk *chunk;
733 gpointer start = ji->code_start;
736 mono_domain_lock (domain);
737 table = domain->jit_info_table;
739 ++mono_stats.jit_info_table_remove_count;
741 chunk_pos = jit_info_table_index (table, start);
742 g_assert (chunk_pos < table->num_chunks);
744 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
747 chunk = table->chunks [chunk_pos];
749 while (pos < chunk->num_elements) {
750 if (chunk->data [pos] == ji)
753 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
754 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
755 <= (guint8*)ji->code_start + ji->code_size);
762 } while (chunk_pos < table->num_chunks);
765 g_assert (chunk->data [pos] == ji);
767 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
769 /* Debugging code, should be removed. */
770 //jit_info_table_check (table);
772 mono_domain_unlock (domain);
775 static MonoAotModuleInfoTable*
776 mono_aot_module_info_table_new (void)
778 return g_array_new (FALSE, FALSE, sizeof (gpointer));
782 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
784 int left = 0, right = table->len;
786 while (left < right) {
787 int pos = (left + right) / 2;
788 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
789 char *start = ainfo->start;
790 char *end = ainfo->end;
794 else if (addr >= end)
804 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
806 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
809 ainfo->image = image;
810 ainfo->start = start;
813 mono_appdomains_lock ();
816 aot_modules = mono_aot_module_info_table_new ();
818 pos = aot_info_table_index (aot_modules, start);
820 g_array_insert_val (aot_modules, pos, ainfo);
822 mono_appdomains_unlock ();
826 mono_jit_info_find_aot_module (guint8* addr)
828 guint left = 0, right;
833 mono_appdomains_lock ();
835 right = aot_modules->len;
836 while (left < right) {
837 guint pos = (left + right) / 2;
838 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
840 if (addr < (guint8*)ai->start)
842 else if (addr >= (guint8*)ai->end)
845 mono_appdomains_unlock ();
850 mono_appdomains_unlock ();
856 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
858 jit_info_find_in_aot_func = func;
862 mono_jit_info_get_code_start (MonoJitInfo* ji)
864 return ji->code_start;
868 mono_jit_info_get_code_size (MonoJitInfo* ji)
870 return ji->code_size;
874 mono_jit_info_get_method (MonoJitInfo* ji)
880 jit_info_key_extract (gpointer value)
882 MonoJitInfo *info = (MonoJitInfo*)value;
888 jit_info_next_value (gpointer value)
890 MonoJitInfo *info = (MonoJitInfo*)value;
892 return (gpointer*)&info->next_jit_code_hash;
896 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
898 mono_internal_hash_table_init (jit_code_hash,
899 mono_aligned_addr_hash,
900 jit_info_key_extract,
901 jit_info_next_value);
906 * @s1: First string to compare
907 * @s2: Second string to compare
909 * Returns FALSE if the strings differ.
912 mono_string_equal (MonoString *s1, MonoString *s2)
914 int l1 = mono_string_length (s1);
915 int l2 = mono_string_length (s2);
922 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
927 * @s: the string to hash
929 * Returns the hash for the string.
932 mono_string_hash (MonoString *s)
934 const guint16 *p = mono_string_chars (s);
935 int i, len = mono_string_length (s);
938 for (i = 0; i < len; i++) {
939 h = (h << 5) - h + *p;
947 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
949 int len = GPOINTER_TO_INT (s1 [0]);
950 if (len != GPOINTER_TO_INT (s2 [0]))
953 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
957 mono_ptrarray_hash (gpointer *s)
960 int len = GPOINTER_TO_INT (s [0]);
963 for (i = 1; i < len; i++)
964 hash += GPOINTER_TO_UINT (s [i]);
970 * Allocate an id for domain and set domain->domain_id.
971 * LOCKING: must be called while holding appdomains_mutex.
972 * We try to assign low numbers to the domain, so it can be used
973 * as an index in data tables to lookup domain-specific info
974 * with minimal memory overhead. We also try not to reuse the
975 * same id too quickly (to help debugging).
978 domain_id_alloc (MonoDomain *domain)
981 if (!appdomains_list) {
982 appdomain_list_size = 2;
983 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
985 for (i = appdomain_next; i < appdomain_list_size; ++i) {
986 if (!appdomains_list [i]) {
992 for (i = 0; i < appdomain_next; ++i) {
993 if (!appdomains_list [i]) {
1000 MonoDomain **new_list;
1001 int new_size = appdomain_list_size * 2;
1002 if (new_size >= (1 << 16))
1003 g_assert_not_reached ();
1004 id = appdomain_list_size;
1005 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1006 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1007 mono_gc_free_fixed (appdomains_list);
1008 appdomains_list = new_list;
1009 appdomain_list_size = new_size;
1011 domain->domain_id = id;
1012 appdomains_list [id] = domain;
1014 if (appdomain_next > appdomain_list_size)
1019 static guint32 domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1020 static gpointer domain_gc_desc = NULL;
1021 static guint32 domain_shadow_serial = 0L;
1024 mono_domain_create (void)
1027 guint32 shadow_serial;
1029 mono_appdomains_lock ();
1030 shadow_serial = domain_shadow_serial++;
1032 if (!domain_gc_desc) {
1033 unsigned int i, bit = 0;
1034 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1035 bit = i / sizeof (gpointer);
1036 domain_gc_bitmap [bit / 32] |= 1 << (bit % 32);
1038 domain_gc_desc = mono_gc_make_descr_from_bitmap (domain_gc_bitmap, bit + 1);
1040 mono_appdomains_unlock ();
1042 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1043 domain->shadow_serial = shadow_serial;
1044 domain->domain = NULL;
1045 domain->setup = NULL;
1046 domain->friendly_name = NULL;
1047 domain->search_path = NULL;
1049 domain->mp = mono_mempool_new ();
1050 domain->code_mp = mono_code_manager_new ();
1051 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1052 domain->domain_assemblies = NULL;
1053 domain->class_vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1054 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1055 domain->static_data_array = NULL;
1056 mono_jit_code_hash_init (&domain->jit_code_hash);
1057 domain->ldstr_table = mono_g_hash_table_new ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal);
1058 domain->jit_info_table = jit_info_table_new ();
1059 domain->class_init_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1060 domain->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1061 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1062 domain->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1063 domain->delegate_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1065 InitializeCriticalSection (&domain->lock);
1066 InitializeCriticalSection (&domain->assemblies_lock);
1068 mono_appdomains_lock ();
1069 domain_id_alloc (domain);
1070 mono_appdomains_unlock ();
1076 * mono_init_internal:
1078 * Creates the initial application domain and initializes the mono_defaults
1080 * This function is guaranteed to not run any IL code.
1081 * If exe_filename is not NULL, the method will determine the required runtime
1082 * from the exe configuration file or the version PE field.
1083 * If runtime_version is not NULL, that runtime version will be used.
1084 * Either exe_filename or runtime_version must be provided.
1086 * Returns: the initial domain.
1089 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1091 static MonoDomain *domain = NULL;
1092 MonoAssembly *ass = NULL;
1093 MonoImageOpenStatus status = MONO_IMAGE_OK;
1094 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1098 g_assert_not_reached ();
1100 MONO_GC_PRE_INIT ();
1102 appdomain_thread_id = TlsAlloc ();
1104 InitializeCriticalSection (&appdomains_mutex);
1106 mono_metadata_init ();
1107 mono_raw_buffer_init ();
1108 mono_images_init ();
1109 mono_assemblies_init ();
1110 mono_classes_init ();
1111 mono_loader_init ();
1112 mono_reflection_init ();
1114 /* FIXME: When should we release this memory? */
1115 MONO_GC_REGISTER_ROOT (appdomains_list);
1117 domain = mono_domain_create ();
1118 mono_root_domain = domain;
1120 SET_APPDOMAIN (domain);
1122 /* Get a list of runtimes supported by the exe */
1123 if (exe_filename != NULL) {
1124 get_runtimes_from_exe (exe_filename, runtimes);
1125 } else if (runtime_version != NULL) {
1126 runtimes [0] = get_runtime_by_version (runtime_version);
1127 runtimes [1] = NULL;
1130 if (runtimes [0] == NULL) {
1131 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1132 runtimes [0] = default_runtime;
1133 runtimes [1] = NULL;
1134 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1135 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1138 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1139 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1140 current_runtime = runtimes [n];
1141 ass = mono_assembly_load_corlib (current_runtime, &status);
1142 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1147 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1149 case MONO_IMAGE_ERROR_ERRNO: {
1150 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1151 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1152 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1153 g_free (corlib_file);
1156 case MONO_IMAGE_IMAGE_INVALID:
1157 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1158 mono_assembly_getrootdir ());
1160 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1161 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1162 mono_assembly_getrootdir ());
1165 /* to suppress compiler warning */
1171 mono_defaults.corlib = mono_assembly_get_image (ass);
1173 mono_defaults.object_class = mono_class_from_name (
1174 mono_defaults.corlib, "System", "Object");
1175 g_assert (mono_defaults.object_class != 0);
1177 mono_defaults.void_class = mono_class_from_name (
1178 mono_defaults.corlib, "System", "Void");
1179 g_assert (mono_defaults.void_class != 0);
1181 mono_defaults.boolean_class = mono_class_from_name (
1182 mono_defaults.corlib, "System", "Boolean");
1183 g_assert (mono_defaults.boolean_class != 0);
1185 mono_defaults.byte_class = mono_class_from_name (
1186 mono_defaults.corlib, "System", "Byte");
1187 g_assert (mono_defaults.byte_class != 0);
1189 mono_defaults.sbyte_class = mono_class_from_name (
1190 mono_defaults.corlib, "System", "SByte");
1191 g_assert (mono_defaults.sbyte_class != 0);
1193 mono_defaults.int16_class = mono_class_from_name (
1194 mono_defaults.corlib, "System", "Int16");
1195 g_assert (mono_defaults.int16_class != 0);
1197 mono_defaults.uint16_class = mono_class_from_name (
1198 mono_defaults.corlib, "System", "UInt16");
1199 g_assert (mono_defaults.uint16_class != 0);
1201 mono_defaults.int32_class = mono_class_from_name (
1202 mono_defaults.corlib, "System", "Int32");
1203 g_assert (mono_defaults.int32_class != 0);
1205 mono_defaults.uint32_class = mono_class_from_name (
1206 mono_defaults.corlib, "System", "UInt32");
1207 g_assert (mono_defaults.uint32_class != 0);
1209 mono_defaults.uint_class = mono_class_from_name (
1210 mono_defaults.corlib, "System", "UIntPtr");
1211 g_assert (mono_defaults.uint_class != 0);
1213 mono_defaults.int_class = mono_class_from_name (
1214 mono_defaults.corlib, "System", "IntPtr");
1215 g_assert (mono_defaults.int_class != 0);
1217 mono_defaults.int64_class = mono_class_from_name (
1218 mono_defaults.corlib, "System", "Int64");
1219 g_assert (mono_defaults.int64_class != 0);
1221 mono_defaults.uint64_class = mono_class_from_name (
1222 mono_defaults.corlib, "System", "UInt64");
1223 g_assert (mono_defaults.uint64_class != 0);
1225 mono_defaults.single_class = mono_class_from_name (
1226 mono_defaults.corlib, "System", "Single");
1227 g_assert (mono_defaults.single_class != 0);
1229 mono_defaults.double_class = mono_class_from_name (
1230 mono_defaults.corlib, "System", "Double");
1231 g_assert (mono_defaults.double_class != 0);
1233 mono_defaults.char_class = mono_class_from_name (
1234 mono_defaults.corlib, "System", "Char");
1235 g_assert (mono_defaults.char_class != 0);
1237 mono_defaults.string_class = mono_class_from_name (
1238 mono_defaults.corlib, "System", "String");
1239 g_assert (mono_defaults.string_class != 0);
1241 mono_defaults.enum_class = mono_class_from_name (
1242 mono_defaults.corlib, "System", "Enum");
1243 g_assert (mono_defaults.enum_class != 0);
1245 mono_defaults.array_class = mono_class_from_name (
1246 mono_defaults.corlib, "System", "Array");
1247 g_assert (mono_defaults.array_class != 0);
1249 mono_defaults.delegate_class = mono_class_from_name (
1250 mono_defaults.corlib, "System", "Delegate");
1251 g_assert (mono_defaults.delegate_class != 0 );
1253 mono_defaults.multicastdelegate_class = mono_class_from_name (
1254 mono_defaults.corlib, "System", "MulticastDelegate");
1255 g_assert (mono_defaults.multicastdelegate_class != 0 );
1257 mono_defaults.asyncresult_class = mono_class_from_name (
1258 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1260 g_assert (mono_defaults.asyncresult_class != 0 );
1262 mono_defaults.waithandle_class = mono_class_from_name (
1263 mono_defaults.corlib, "System.Threading", "WaitHandle");
1264 g_assert (mono_defaults.waithandle_class != 0 );
1266 mono_defaults.typehandle_class = mono_class_from_name (
1267 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1268 g_assert (mono_defaults.typehandle_class != 0);
1270 mono_defaults.methodhandle_class = mono_class_from_name (
1271 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1272 g_assert (mono_defaults.methodhandle_class != 0);
1274 mono_defaults.fieldhandle_class = mono_class_from_name (
1275 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1276 g_assert (mono_defaults.fieldhandle_class != 0);
1278 mono_defaults.systemtype_class = mono_class_from_name (
1279 mono_defaults.corlib, "System", "Type");
1280 g_assert (mono_defaults.systemtype_class != 0);
1282 mono_defaults.monotype_class = mono_class_from_name (
1283 mono_defaults.corlib, "System", "MonoType");
1284 g_assert (mono_defaults.monotype_class != 0);
1286 mono_defaults.exception_class = mono_class_from_name (
1287 mono_defaults.corlib, "System", "Exception");
1288 g_assert (mono_defaults.exception_class != 0);
1290 mono_defaults.threadabortexception_class = mono_class_from_name (
1291 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1292 g_assert (mono_defaults.threadabortexception_class != 0);
1294 mono_defaults.thread_class = mono_class_from_name (
1295 mono_defaults.corlib, "System.Threading", "Thread");
1296 g_assert (mono_defaults.thread_class != 0);
1298 mono_defaults.appdomain_class = mono_class_from_name (
1299 mono_defaults.corlib, "System", "AppDomain");
1300 g_assert (mono_defaults.appdomain_class != 0);
1302 mono_defaults.transparent_proxy_class = mono_class_from_name (
1303 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1304 g_assert (mono_defaults.transparent_proxy_class != 0);
1306 mono_defaults.real_proxy_class = mono_class_from_name (
1307 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1308 g_assert (mono_defaults.real_proxy_class != 0);
1310 mono_defaults.mono_method_message_class = mono_class_from_name (
1311 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1312 g_assert (mono_defaults.mono_method_message_class != 0);
1314 mono_defaults.field_info_class = mono_class_from_name (
1315 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1316 g_assert (mono_defaults.field_info_class != 0);
1318 mono_defaults.method_info_class = mono_class_from_name (
1319 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1320 g_assert (mono_defaults.method_info_class != 0);
1322 mono_defaults.stringbuilder_class = mono_class_from_name (
1323 mono_defaults.corlib, "System.Text", "StringBuilder");
1324 g_assert (mono_defaults.stringbuilder_class != 0);
1326 mono_defaults.math_class = mono_class_from_name (
1327 mono_defaults.corlib, "System", "Math");
1328 g_assert (mono_defaults.math_class != 0);
1330 mono_defaults.stack_frame_class = mono_class_from_name (
1331 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1332 g_assert (mono_defaults.stack_frame_class != 0);
1334 mono_defaults.stack_trace_class = mono_class_from_name (
1335 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1336 g_assert (mono_defaults.stack_trace_class != 0);
1338 mono_defaults.marshal_class = mono_class_from_name (
1339 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1340 g_assert (mono_defaults.marshal_class != 0);
1342 mono_defaults.iserializeable_class = mono_class_from_name (
1343 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1344 g_assert (mono_defaults.iserializeable_class != 0);
1346 mono_defaults.serializationinfo_class = mono_class_from_name (
1347 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1348 g_assert (mono_defaults.serializationinfo_class != 0);
1350 mono_defaults.streamingcontext_class = mono_class_from_name (
1351 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1352 g_assert (mono_defaults.streamingcontext_class != 0);
1354 mono_defaults.typed_reference_class = mono_class_from_name (
1355 mono_defaults.corlib, "System", "TypedReference");
1356 g_assert (mono_defaults.typed_reference_class != 0);
1358 mono_defaults.argumenthandle_class = mono_class_from_name (
1359 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1360 g_assert (mono_defaults.argumenthandle_class != 0);
1362 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1363 mono_defaults.corlib, "System", "MarshalByRefObject");
1364 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1366 mono_defaults.monitor_class = mono_class_from_name (
1367 mono_defaults.corlib, "System.Threading", "Monitor");
1368 g_assert (mono_defaults.monitor_class != 0);
1370 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1371 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1372 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1374 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1375 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1377 mono_defaults.executioncontext_class = mono_class_from_name (
1378 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1380 mono_defaults.internals_visible_class = mono_class_from_name (
1381 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1384 * mscorlib needs a little help, only now it can load its friends list (after we have
1385 * loaded the InternalsVisibleToAttribute), load it now
1387 mono_assembly_load_friends (ass);
1389 mono_defaults.safehandle_class = mono_class_from_name (
1390 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1392 mono_defaults.handleref_class = mono_class_from_name (
1393 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1395 mono_defaults.attribute_class = mono_class_from_name (
1396 mono_defaults.corlib, "System", "Attribute");
1398 mono_defaults.customattribute_data_class = mono_class_from_name (
1399 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1401 /* these are initialized lazily when COM features are used */
1402 mono_defaults.variant_class = NULL;
1403 mono_defaults.com_object_class = NULL;
1404 mono_defaults.com_interop_proxy_class = NULL;
1405 mono_defaults.iunknown_class = NULL;
1406 mono_defaults.idispatch_class = NULL;
1409 * Note that mono_defaults.generic_*_class is only non-NULL if we're
1410 * using the 2.0 corlib.
1412 mono_class_init (mono_defaults.array_class);
1413 mono_defaults.generic_nullable_class = mono_class_from_name (
1414 mono_defaults.corlib, "System", "Nullable`1");
1415 mono_defaults.generic_ilist_class = mono_class_from_name (
1416 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1418 domain->friendly_name = g_path_get_basename (filename);
1426 * Creates the initial application domain and initializes the mono_defaults
1428 * This function is guaranteed to not run any IL code.
1429 * The runtime is initialized using the default runtime version.
1431 * Returns: the initial domain.
1434 mono_init (const char *domain_name)
1436 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1440 * mono_init_from_assembly:
1442 * Creates the initial application domain and initializes the mono_defaults
1444 * This function is guaranteed to not run any IL code.
1445 * The runtime is initialized using the runtime version required by the
1446 * provided executable. The version is determined by looking at the exe
1447 * configuration file and the version PE field)
1449 * Returns: the initial domain.
1452 mono_init_from_assembly (const char *domain_name, const char *filename)
1454 return mono_init_internal (domain_name, filename, NULL);
1458 * mono_init_version:
1460 * Creates the initial application domain and initializes the mono_defaults
1462 * This function is guaranteed to not run any IL code.
1463 * The runtime is initialized using the provided rutime version.
1465 * Returns: the initial domain.
1468 mono_init_version (const char *domain_name, const char *version)
1470 return mono_init_internal (domain_name, NULL, version);
1474 * mono_init_com_types:
1476 * Initializes all types needed for COM Interop in mono_defaults structure.
1479 mono_init_com_types (void)
1481 static gboolean initialized = FALSE;
1486 /* FIXME: do I need some threading protection here */
1488 g_assert (mono_defaults.corlib);
1490 mono_defaults.variant_class = mono_class_from_name (
1491 mono_defaults.corlib, "System", "Variant");
1492 g_assert (mono_defaults.variant_class != 0);
1494 mono_defaults.com_object_class = mono_class_from_name (
1495 mono_defaults.corlib, "System", "__ComObject");
1496 g_assert (mono_defaults.com_object_class != 0);
1498 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1499 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1500 g_assert (mono_defaults.com_interop_proxy_class != 0);
1502 mono_defaults.iunknown_class = mono_class_from_name (
1503 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1504 g_assert (mono_defaults.iunknown_class != 0);
1506 mono_defaults.idispatch_class = mono_class_from_name (
1507 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1508 g_assert (mono_defaults.idispatch_class != 0);
1516 * Cleans up all metadata modules.
1521 mono_loader_cleanup ();
1522 mono_classes_cleanup ();
1523 mono_assemblies_cleanup ();
1524 mono_images_cleanup ();
1525 mono_raw_buffer_cleanup ();
1526 mono_metadata_cleanup ();
1528 TlsFree (appdomain_thread_id);
1529 DeleteCriticalSection (&appdomains_mutex);
1533 * mono_get_root_domain:
1535 * The root AppDomain is the initial domain created by the runtime when it is
1536 * initialized. Programs execute on this AppDomain, but can create new ones
1537 * later. Currently there is no unmanaged API to create new AppDomains, this
1538 * must be done from managed code.
1540 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1543 mono_get_root_domain (void)
1545 return mono_root_domain;
1551 * Returns: the current domain, to obtain the root domain use
1552 * mono_get_root_domain().
1557 return GET_APPDOMAIN ();
1561 * mono_domain_set_internal:
1562 * @domain: the new domain
1564 * Sets the current domain to @domain.
1567 mono_domain_set_internal (MonoDomain *domain)
1569 SET_APPDOMAIN (domain);
1570 SET_APPCONTEXT (domain->default_context);
1574 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1580 * Create a copy of the data to avoid calling the user callback
1581 * inside the lock because that could lead to deadlocks.
1582 * We can do this because this function is not perf. critical.
1584 mono_appdomains_lock ();
1585 size = appdomain_list_size;
1586 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1587 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1588 mono_appdomains_unlock ();
1590 for (i = 0; i < size; ++i) {
1592 func (copy [i], user_data);
1595 mono_gc_free_fixed (copy);
1599 * mono_domain_assembly_open:
1600 * @domain: the application domain
1601 * @name: file name of the assembly
1603 * fixme: maybe we should integrate this with mono_assembly_open ??
1606 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1611 mono_domain_assemblies_lock (domain);
1612 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1614 if (strcmp (name, ass->aname.name) == 0) {
1615 mono_domain_assemblies_unlock (domain);
1619 mono_domain_assemblies_unlock (domain);
1621 if (!(ass = mono_assembly_open (name, NULL)))
1628 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
1630 MonoJitDynamicMethodInfo *di = value;
1631 mono_code_manager_destroy (di->code_mp);
1636 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
1638 g_slist_free (value);
1642 mono_domain_free (MonoDomain *domain, gboolean force)
1645 if ((domain == mono_root_domain) && !force) {
1646 g_warning ("cant unload root domain");
1650 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_UNLOAD, domain->domain_id, 0);
1652 mono_appdomains_lock ();
1653 appdomains_list [domain->domain_id] = NULL;
1654 mono_appdomains_unlock ();
1656 /* FIXME: free delegate_hash_table when it's used */
1657 if (domain->search_path) {
1658 g_strfreev (domain->search_path);
1659 domain->search_path = NULL;
1661 domain->create_proxy_for_type_method = NULL;
1662 domain->private_invoke_method = NULL;
1663 domain->default_context = NULL;
1664 domain->out_of_memory_ex = NULL;
1665 domain->null_reference_ex = NULL;
1666 domain->stack_overflow_ex = NULL;
1667 domain->entry_assembly = NULL;
1668 /* must do this early as it accesses fields and types */
1669 if (domain->special_static_fields) {
1670 mono_alloc_special_static_data_free (domain->special_static_fields);
1671 g_hash_table_destroy (domain->special_static_fields);
1672 domain->special_static_fields = NULL;
1674 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1675 MonoAssembly *ass = tmp->data;
1676 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);
1677 mono_assembly_close (ass);
1679 g_slist_free (domain->domain_assemblies);
1680 domain->domain_assemblies = NULL;
1682 g_free (domain->friendly_name);
1683 domain->friendly_name = NULL;
1684 mono_g_hash_table_destroy (domain->env);
1686 g_hash_table_destroy (domain->class_vtable_hash);
1687 domain->class_vtable_hash = NULL;
1688 g_hash_table_destroy (domain->proxy_vtable_hash);
1689 domain->proxy_vtable_hash = NULL;
1690 if (domain->static_data_array) {
1691 mono_gc_free_fixed (domain->static_data_array);
1692 domain->static_data_array = NULL;
1694 mono_internal_hash_table_destroy (&domain->jit_code_hash);
1695 if (domain->dynamic_code_hash) {
1696 g_hash_table_foreach (domain->dynamic_code_hash, dynamic_method_info_free, NULL);
1697 g_hash_table_destroy (domain->dynamic_code_hash);
1698 domain->dynamic_code_hash = NULL;
1700 mono_g_hash_table_destroy (domain->ldstr_table);
1701 domain->ldstr_table = NULL;
1702 jit_info_table_free (domain->jit_info_table);
1703 domain->jit_info_table = NULL;
1704 #ifdef DEBUG_DOMAIN_UNLOAD
1705 mono_mempool_invalidate (domain->mp);
1706 mono_code_manager_invalidate (domain->code_mp);
1708 mono_mempool_destroy (domain->mp);
1710 mono_code_manager_destroy (domain->code_mp);
1711 domain->code_mp = NULL;
1713 if (domain->jump_target_hash) {
1714 g_hash_table_foreach (domain->jump_target_hash, delete_jump_list, NULL);
1715 g_hash_table_destroy (domain->jump_target_hash);
1716 domain->jump_target_hash = NULL;
1718 if (domain->type_hash) {
1719 mono_g_hash_table_destroy (domain->type_hash);
1720 domain->type_hash = NULL;
1722 if (domain->refobject_hash) {
1723 mono_g_hash_table_destroy (domain->refobject_hash);
1724 domain->refobject_hash = NULL;
1726 if (domain->type_init_exception_hash) {
1727 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1728 domain->type_init_exception_hash = NULL;
1730 g_hash_table_destroy (domain->class_init_trampoline_hash);
1731 domain->class_init_trampoline_hash = NULL;
1732 g_hash_table_destroy (domain->jump_trampoline_hash);
1733 domain->jump_trampoline_hash = NULL;
1734 g_hash_table_destroy (domain->finalizable_objects_hash);
1735 domain->finalizable_objects_hash = NULL;
1736 g_hash_table_destroy (domain->jit_trampoline_hash);
1737 domain->jit_trampoline_hash = NULL;
1738 g_hash_table_destroy (domain->delegate_trampoline_hash);
1739 domain->delegate_trampoline_hash = NULL;
1740 if (domain->delegate_invoke_impl_with_target_hash) {
1741 g_hash_table_destroy (domain->delegate_invoke_impl_with_target_hash);
1742 domain->delegate_invoke_impl_with_target_hash = NULL;
1744 if (domain->delegate_invoke_impl_no_target_hash) {
1745 g_hash_table_destroy (domain->delegate_invoke_impl_no_target_hash);
1746 domain->delegate_invoke_impl_no_target_hash = NULL;
1748 DeleteCriticalSection (&domain->assemblies_lock);
1749 DeleteCriticalSection (&domain->lock);
1750 domain->setup = NULL;
1752 /* FIXME: anything else required ? */
1754 mono_gc_free_fixed (domain);
1756 if ((domain == mono_root_domain))
1757 mono_root_domain = NULL;
1761 * mono_domain_get_id:
1764 * Returns: the a domain for a specific domain id.
1767 mono_domain_get_by_id (gint32 domainid)
1769 MonoDomain * domain;
1771 mono_appdomains_lock ();
1772 if (domainid < appdomain_list_size)
1773 domain = appdomains_list [domainid];
1776 mono_appdomains_unlock ();
1782 mono_domain_get_id (MonoDomain *domain)
1784 return domain->domain_id;
1788 mono_context_set (MonoAppContext * new_context)
1790 SET_APPCONTEXT (new_context);
1794 mono_context_get (void)
1796 return GET_APPCONTEXT ();
1799 /* LOCKING: the caller holds the lock for this domain */
1801 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
1803 /* The first entry in the array is the index of the next free slot
1804 * and the total size of the array
1807 if (domain->static_data_array) {
1808 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
1809 next = GPOINTER_TO_INT (domain->static_data_array [0]);
1811 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), NULL);
1812 memcpy (new_array, domain->static_data_array, sizeof (gpointer) * size);
1814 new_array [1] = GINT_TO_POINTER (size);
1815 mono_gc_free_fixed (domain->static_data_array);
1816 domain->static_data_array = new_array;
1820 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, NULL);
1822 new_array [0] = GINT_TO_POINTER (next);
1823 new_array [1] = GINT_TO_POINTER (size);
1824 domain->static_data_array = new_array;
1826 domain->static_data_array [next++] = data;
1827 domain->static_data_array [0] = GINT_TO_POINTER (next);
1831 mono_get_corlib (void)
1833 return mono_defaults.corlib;
1837 mono_get_object_class (void)
1839 return mono_defaults.object_class;
1843 mono_get_byte_class (void)
1845 return mono_defaults.byte_class;
1849 mono_get_void_class (void)
1851 return mono_defaults.void_class;
1855 mono_get_boolean_class (void)
1857 return mono_defaults.boolean_class;
1861 mono_get_sbyte_class (void)
1863 return mono_defaults.sbyte_class;
1867 mono_get_int16_class (void)
1869 return mono_defaults.int16_class;
1873 mono_get_uint16_class (void)
1875 return mono_defaults.uint16_class;
1879 mono_get_int32_class (void)
1881 return mono_defaults.int32_class;
1885 mono_get_uint32_class (void)
1887 return mono_defaults.uint32_class;
1891 mono_get_intptr_class (void)
1893 return mono_defaults.int_class;
1897 mono_get_uintptr_class (void)
1899 return mono_defaults.uint_class;
1903 mono_get_int64_class (void)
1905 return mono_defaults.int64_class;
1909 mono_get_uint64_class (void)
1911 return mono_defaults.uint64_class;
1915 mono_get_single_class (void)
1917 return mono_defaults.single_class;
1921 mono_get_double_class (void)
1923 return mono_defaults.double_class;
1927 mono_get_char_class (void)
1929 return mono_defaults.char_class;
1933 mono_get_string_class (void)
1935 return mono_defaults.string_class;
1939 mono_get_enum_class (void)
1941 return mono_defaults.enum_class;
1945 mono_get_array_class (void)
1947 return mono_defaults.array_class;
1951 mono_get_thread_class (void)
1953 return mono_defaults.thread_class;
1957 mono_get_exception_class (void)
1959 return mono_defaults.exception_class;
1963 static char* get_attribute_value (const gchar **attribute_names,
1964 const gchar **attribute_values,
1965 const char *att_name)
1968 for (n=0; attribute_names[n] != NULL; n++) {
1969 if (strcmp (attribute_names[n], att_name) == 0)
1970 return g_strdup (attribute_values[n]);
1975 static void start_element (GMarkupParseContext *context,
1976 const gchar *element_name,
1977 const gchar **attribute_names,
1978 const gchar **attribute_values,
1982 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
1984 if (strcmp (element_name, "configuration") == 0) {
1985 app_config->configuration_count++;
1988 if (strcmp (element_name, "startup") == 0) {
1989 app_config->startup_count++;
1993 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
1996 if (strcmp (element_name, "requiredRuntime") == 0) {
1997 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
1998 } else if (strcmp (element_name, "supportedRuntime") == 0) {
1999 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2000 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2004 static void end_element (GMarkupParseContext *context,
2005 const gchar *element_name,
2009 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2011 if (strcmp (element_name, "configuration") == 0) {
2012 app_config->configuration_count--;
2013 } else if (strcmp (element_name, "startup") == 0) {
2014 app_config->startup_count--;
2018 static const GMarkupParser
2027 static AppConfigInfo *
2028 app_config_parse (const char *exe_filename)
2030 AppConfigInfo *app_config;
2031 GMarkupParseContext *context;
2035 const char *bundled_config;
2036 char *config_filename;
2038 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2040 if (bundled_config) {
2041 text = g_strdup (bundled_config);
2042 len = strlen (text);
2044 config_filename = g_strconcat (exe_filename, ".config", NULL);
2046 if (stat (config_filename, &buf) != 0) {
2047 g_free (config_filename);
2051 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2052 g_free (config_filename);
2055 g_free (config_filename);
2058 app_config = g_new0 (AppConfigInfo, 1);
2060 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2061 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2062 g_markup_parse_context_end_parse (context, NULL);
2064 g_markup_parse_context_free (context);
2070 app_config_free (AppConfigInfo* app_config)
2073 GSList *list = app_config->supported_runtimes;
2074 while (list != NULL) {
2075 rt = (char*)list->data;
2077 list = g_slist_next (list);
2079 g_slist_free (app_config->supported_runtimes);
2080 g_free (app_config->required_runtime);
2081 g_free (app_config);
2085 static const MonoRuntimeInfo*
2086 get_runtime_by_version (const char *version)
2089 int max = G_N_ELEMENTS (supported_runtimes);
2091 for (n=0; n<max; n++) {
2092 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2093 return &supported_runtimes[n];
2099 get_runtimes_from_exe (const char *exe_file, const MonoRuntimeInfo** runtimes)
2101 AppConfigInfo* app_config;
2103 const MonoRuntimeInfo* runtime = NULL;
2104 MonoImage *image = NULL;
2106 app_config = app_config_parse (exe_file);
2108 if (app_config != NULL) {
2109 /* Check supportedRuntime elements, if none is supported, fail.
2110 * If there are no such elements, look for a requiredRuntime element.
2112 if (app_config->supported_runtimes != NULL) {
2114 GSList *list = app_config->supported_runtimes;
2115 while (list != NULL) {
2116 version = (char*) list->data;
2117 runtime = get_runtime_by_version (version);
2118 if (runtime != NULL)
2119 runtimes [n++] = runtime;
2120 list = g_slist_next (list);
2122 runtimes [n] = NULL;
2123 app_config_free (app_config);
2127 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2128 if (app_config->required_runtime != NULL) {
2129 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2130 runtimes [1] = NULL;
2131 app_config_free (app_config);
2134 app_config_free (app_config);
2137 /* Look for a runtime with the exact version */
2138 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2141 image = mono_image_open (exe_file, NULL);
2143 if (image == NULL) {
2144 /* The image is wrong or the file was not found. In this case return
2145 * a default runtime and leave to the initialization method the work of
2146 * reporting the error.
2148 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2149 runtimes [1] = NULL;
2154 * FIXME: This would cause us to unload the image, and it will be loaded again later.
2155 * Disabling it will mean the initial exe will not be unloaded on shutdown.
2157 //mono_image_close (image);
2159 runtimes [0] = get_runtime_by_version (image->version);
2160 runtimes [1] = NULL;
2165 * mono_get_runtime_info:
2167 * Returns: the version of the current runtime instance.
2169 const MonoRuntimeInfo*
2170 mono_get_runtime_info (void)
2172 return current_runtime;
2176 mono_debugger_check_runtime_version (const char *filename)
2178 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2179 const MonoRuntimeInfo *rinfo;
2181 get_runtimes_from_exe (filename, runtimes);
2182 rinfo = runtimes [0];
2185 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2187 if (rinfo != current_runtime)
2188 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2189 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2190 filename, rinfo->runtime_version);