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>
38 /* #define DEBUG_DOMAIN_UNLOAD */
40 /* we need to use both the Tls* functions and __thread because
41 * some archs may generate faster jit code with one meachanism
42 * or the other (we used to do it because tls slots were GC-tracked,
43 * but we can't depend on this).
45 static guint32 appdomain_thread_id = -1;
48 static __thread MonoDomain * tls_appdomain MONO_TLS_FAST;
49 #define GET_APPDOMAIN() tls_appdomain
50 #define SET_APPDOMAIN(x) do { \
52 TlsSetValue (appdomain_thread_id, x); \
57 #define GET_APPDOMAIN() ((MonoDomain *)TlsGetValue (appdomain_thread_id))
58 #define SET_APPDOMAIN(x) TlsSetValue (appdomain_thread_id, x);
62 #define GET_APPCONTEXT() (mono_thread_current ()->current_appcontext)
63 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_current (), current_appcontext, (x))
65 static guint16 appdomain_list_size = 0;
66 static guint16 appdomain_next = 0;
67 static MonoDomain **appdomains_list = NULL;
68 static MonoImage *exe_image;
70 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
71 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
72 static CRITICAL_SECTION appdomains_mutex;
74 static MonoDomain *mono_root_domain = NULL;
77 static int max_domain_code_size = 0;
78 static int max_domain_code_alloc = 0;
79 static int total_domain_code_alloc = 0;
81 /* AppConfigInfo: Information about runtime versions supported by an
85 GSList *supported_runtimes;
86 char *required_runtime;
87 int configuration_count;
92 * AotModuleInfo: Contains information about AOT modules.
99 static const MonoRuntimeInfo *current_runtime = NULL;
101 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
104 * Contains information about AOT loaded code.
106 static MonoAotModuleInfoTable *aot_modules = NULL;
108 /* This is the list of runtime versions supported by this JIT.
110 static const MonoRuntimeInfo supported_runtimes[] = {
111 {"v1.0.3705", "1.0", { {1,0,5000,0}, {7,0,5000,0} } },
112 {"v1.1.4322", "1.0", { {1,0,5000,0}, {7,0,5000,0} } },
113 {"v2.0.50215","2.0", { {2,0,0,0}, {8,0,0,0} } },
114 {"v2.0.50727","2.0", { {2,0,0,0}, {8,0,0,0} } },
115 {"moonlight", "2.1", { {2,1,0,0}, {9,0,0,0} } },
119 /* The stable runtime version */
120 #define DEFAULT_RUNTIME_VERSION "v1.1.4322"
122 /* This is intentionally not in the header file, so people don't misuse it. */
123 extern void _mono_debug_init_corlib (MonoDomain *domain);
126 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
128 static const MonoRuntimeInfo*
129 get_runtime_by_version (const char *version);
132 mono_jit_info_find_aot_module (guint8* addr);
135 mono_domain_get_tls_key (void)
137 return appdomain_thread_id;
141 mono_domain_get_tls_offset (void)
144 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
145 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
150 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
151 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
152 #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)
154 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
155 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
157 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == NULL)
159 #define JIT_INFO_TABLE_HAZARD_INDEX 0
160 #define JIT_INFO_HAZARD_INDEX 1
163 jit_info_table_num_elements (MonoJitInfoTable *table)
166 int num_elements = 0;
168 for (i = 0; i < table->num_chunks; ++i) {
169 MonoJitInfoTableChunk *chunk = table->chunks [i];
170 int chunk_num_elements = chunk->num_elements;
173 for (j = 0; j < chunk_num_elements; ++j) {
174 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
182 static MonoJitInfoTableChunk*
183 jit_info_table_new_chunk (void)
185 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
191 static MonoJitInfoTable *
192 jit_info_table_new (void)
194 MonoJitInfoTable *table = g_malloc0 (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*));
196 table->num_chunks = 1;
197 table->chunks [0] = jit_info_table_new_chunk ();
203 jit_info_table_free (MonoJitInfoTable *table)
206 int num_chunks = table->num_chunks;
208 /* At this point we assume that there are no other threads
209 still accessing the table, so we don't have to worry about
210 hazardous pointers. */
212 for (i = 0; i < num_chunks; ++i) {
213 MonoJitInfoTableChunk *chunk = table->chunks [i];
217 if (--chunk->refcount > 0)
220 num_elements = chunk->num_elements;
221 for (j = 0; j < num_elements; ++j) {
222 MonoJitInfo *ji = chunk->data [j];
224 if (IS_JIT_INFO_TOMBSTONE (ji))
234 /* Can be called with hp==NULL, in which case it acts as an ordinary
235 pointer fetch. It's used that way indirectly from
236 mono_jit_info_table_add(), which doesn't have to care about hazards
237 because it holds the respective domain lock. */
239 get_hazardous_pointer (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index)
244 /* Get the pointer */
246 /* If we don't have hazard pointers just return the
250 /* Make it hazardous */
251 mono_hazard_pointer_set (hp, hazard_index, p);
252 /* Check that it's still the same. If not, try
255 mono_hazard_pointer_clear (hp, hazard_index);
264 /* The jit_info_table is sorted in ascending order by the end
265 * addresses of the compiled methods. The reason why we have to do
266 * this is that once we introduce tombstones, it becomes possible for
267 * code ranges to overlap, and if we sort by code start and insert at
268 * the back of the table, we cannot guarantee that we won't overlook
271 * There are actually two possible ways to do the sorting and
272 * inserting which work with our lock-free mechanism:
274 * 1. Sort by start address and insert at the front. When looking for
275 * an entry, find the last one with a start address lower than the one
276 * you're looking for, then work your way to the front of the table.
278 * 2. Sort by end address and insert at the back. When looking for an
279 * entry, find the first one with an end address higher than the one
280 * you're looking for, then work your way to the end of the table.
282 * We chose the latter out of convenience.
285 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
287 int left = 0, right = table->num_chunks;
289 g_assert (left < right);
292 int pos = (left + right) / 2;
293 MonoJitInfoTableChunk *chunk = table->chunks [pos];
295 if (addr < chunk->last_code_end)
299 } while (left < right);
300 g_assert (left == right);
302 if (left >= table->num_chunks)
303 return table->num_chunks - 1;
308 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
310 int left = 0, right = chunk->num_elements;
312 while (left < right) {
313 int pos = (left + right) / 2;
314 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
315 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
322 g_assert (left == right);
328 mono_jit_info_table_find (MonoDomain *domain, char *addr)
330 MonoJitInfoTable *table;
333 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
335 ++mono_stats.jit_info_table_lookup_count;
337 /* First we have to get the domain's jit_info_table. This is
338 complicated by the fact that a writer might substitute a
339 new table and free the old one. What the writer guarantees
340 us is that it looks at the hazard pointers after it has
341 changed the jit_info_table pointer. So, if we guard the
342 table by a hazard pointer and make sure that the pointer is
343 still there after we've made it hazardous, we don't have to
344 worry about the writer freeing the table. */
345 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
347 chunk_pos = jit_info_table_index (table, (gint8*)addr);
348 g_assert (chunk_pos < table->num_chunks);
350 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
352 /* We now have a position that's very close to that of the
353 first element whose end address is higher than the one
354 we're looking for. If we don't have the exact position,
355 then we have a position below that one, so we'll just
356 search upward until we find our element. */
358 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
360 while (pos < chunk->num_elements) {
361 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
365 if (IS_JIT_INFO_TOMBSTONE (ji)) {
366 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
369 if ((gint8*)addr >= (gint8*)ji->code_start
370 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
371 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
372 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
376 /* If we find a non-tombstone element which is already
377 beyond what we're looking for, we have to end the
379 if ((gint8*)addr < (gint8*)ji->code_start)
385 } while (chunk_pos < table->num_chunks);
387 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
388 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
390 /* maybe it is shared code, so we also search in the root domain */
392 if (domain != mono_root_domain)
393 ji = mono_jit_info_table_find (mono_root_domain, addr);
396 /* Maybe its an AOT module */
397 MonoImage *image = mono_jit_info_find_aot_module ((guint8*)addr);
399 ji = jit_info_find_in_aot_func (domain, image, addr);
406 jit_info_table_check (MonoJitInfoTable *table)
410 for (i = 0; i < table->num_chunks; ++i) {
411 MonoJitInfoTableChunk *chunk = table->chunks [i];
414 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
415 if (chunk->refcount > 10)
416 printf("warning: chunk refcount is %d\n", chunk->refcount);
417 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
419 for (j = 0; j < chunk->num_elements; ++j) {
420 MonoJitInfo *this = chunk->data [j];
423 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
425 if (j < chunk->num_elements - 1)
426 next = chunk->data [j + 1];
427 else if (i < table->num_chunks - 1) {
430 for (k = i + 1; k < table->num_chunks; ++k)
431 if (table->chunks [k]->num_elements > 0)
434 if (k >= table->num_chunks)
437 g_assert (table->chunks [k]->num_elements > 0);
438 next = table->chunks [k]->data [0];
442 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
447 static MonoJitInfoTable*
448 jit_info_table_realloc (MonoJitInfoTable *old)
451 int num_elements = jit_info_table_num_elements (old);
454 int new_chunk, new_element;
455 MonoJitInfoTable *new;
457 /* number of needed places for elements needed */
458 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
459 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
461 new = g_malloc (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*) * num_chunks);
462 new->num_chunks = num_chunks;
464 for (i = 0; i < num_chunks; ++i)
465 new->chunks [i] = jit_info_table_new_chunk ();
469 for (i = 0; i < old->num_chunks; ++i) {
470 MonoJitInfoTableChunk *chunk = old->chunks [i];
471 int chunk_num_elements = chunk->num_elements;
474 for (j = 0; j < chunk_num_elements; ++j) {
475 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
476 g_assert (new_chunk < num_chunks);
477 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
478 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
479 new->chunks [new_chunk]->num_elements = new_element;
487 if (new_chunk < num_chunks) {
488 g_assert (new_chunk == num_chunks - 1);
489 new->chunks [new_chunk]->num_elements = new_element;
490 g_assert (new->chunks [new_chunk]->num_elements > 0);
493 for (i = 0; i < num_chunks; ++i) {
494 MonoJitInfoTableChunk *chunk = new->chunks [i];
495 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
497 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
504 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
506 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
507 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
509 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
511 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
512 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
514 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
515 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
517 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
518 + new1->data [new1->num_elements - 1]->code_size;
519 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
520 + new2->data [new2->num_elements - 1]->code_size;
526 static MonoJitInfoTable*
527 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
529 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
530 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
533 new_table->num_chunks = table->num_chunks + 1;
536 for (i = 0; i < table->num_chunks; ++i) {
537 if (table->chunks [i] == chunk) {
538 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
541 new_table->chunks [j] = table->chunks [i];
542 ++new_table->chunks [j]->refcount;
547 g_assert (j == new_table->num_chunks);
552 static MonoJitInfoTableChunk*
553 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
555 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
559 for (i = 0; i < old->num_elements; ++i) {
560 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
561 new->data [j++] = old->data [i];
564 new->num_elements = j;
565 if (new->num_elements > 0)
566 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
568 new->last_code_end = old->last_code_end;
573 static MonoJitInfoTable*
574 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
576 MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
577 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
580 new_table->num_chunks = table->num_chunks;
583 for (i = 0; i < table->num_chunks; ++i) {
584 if (table->chunks [i] == chunk)
585 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
587 new_table->chunks [j] = table->chunks [i];
588 ++new_table->chunks [j]->refcount;
593 g_assert (j == new_table->num_chunks);
598 /* As we add an element to the table the case can arise that the chunk
599 * to which we need to add is already full. In that case we have to
600 * allocate a new table and do something about that chunk. We have
601 * several strategies:
603 * If the number of elements in the table is below the low watermark
604 * or above the high watermark, we reallocate the whole table.
605 * Otherwise we only concern ourselves with the overflowing chunk:
607 * If there are no tombstones in the chunk then we split the chunk in
608 * two, each half full.
610 * If the chunk does contain tombstones, we just make a new copy of
611 * the chunk without the tombstones, which will have room for at least
612 * the one element we have to add.
614 static MonoJitInfoTable*
615 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
617 int num_elements = jit_info_table_num_elements (table);
620 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
621 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
622 //printf ("reallocing table\n");
623 return jit_info_table_realloc (table);
626 /* count the number of non-tombstone elements in the chunk */
628 for (i = 0; i < chunk->num_elements; ++i) {
629 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
633 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
634 //printf ("splitting chunk\n");
635 return jit_info_table_copy_and_split_chunk (table, chunk);
638 //printf ("purifying chunk\n");
639 return jit_info_table_copy_and_purify_chunk (table, chunk);
642 /* We add elements to the table by first making space for them by
643 * shifting the elements at the back to the right, one at a time.
644 * This results in duplicate entries during the process, but during
645 * all the time the table is in a sorted state. Also, when an element
646 * is replaced by another one, the element that replaces it has an end
647 * address that is equal to or lower than that of the replaced
648 * element. That property is necessary to guarantee that when
649 * searching for an element we end up at a position not higher than
650 * the one we're looking for (i.e. we either find the element directly
651 * or we end up to the left of it).
654 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
656 MonoJitInfoTable *table;
658 MonoJitInfoTableChunk *chunk;
662 g_assert (ji->method != NULL);
664 mono_domain_lock (domain);
666 ++mono_stats.jit_info_table_insert_count;
668 table = domain->jit_info_table;
671 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
672 g_assert (chunk_pos < table->num_chunks);
673 chunk = table->chunks [chunk_pos];
675 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
676 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
678 /* Debugging code, should be removed. */
679 //jit_info_table_check (new_table);
681 domain->jit_info_table = new_table;
682 mono_memory_barrier ();
683 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free);
689 /* Debugging code, should be removed. */
690 //jit_info_table_check (table);
692 num_elements = chunk->num_elements;
694 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
696 /* First we need to size up the chunk by one, by copying the
697 last item, or inserting the first one, if the table is
699 if (num_elements > 0)
700 chunk->data [num_elements] = chunk->data [num_elements - 1];
702 chunk->data [0] = ji;
703 mono_memory_write_barrier ();
704 chunk->num_elements = ++num_elements;
706 /* Shift the elements up one by one. */
707 for (i = num_elements - 2; i >= pos; --i) {
708 mono_memory_write_barrier ();
709 chunk->data [i + 1] = chunk->data [i];
712 /* Now we have room and can insert the new item. */
713 mono_memory_write_barrier ();
714 chunk->data [pos] = ji;
716 /* Set the high code end address chunk entry. */
717 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
718 + chunk->data [chunk->num_elements - 1]->code_size;
720 /* Debugging code, should be removed. */
721 //jit_info_table_check (table);
723 mono_domain_unlock (domain);
727 mono_jit_info_make_tombstone (MonoJitInfo *ji)
729 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
731 tombstone->code_start = ji->code_start;
732 tombstone->code_size = ji->code_size;
733 tombstone->method = NULL;
739 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
741 MonoJitInfoTable *table;
742 MonoJitInfoTableChunk *chunk;
743 gpointer start = ji->code_start;
746 mono_domain_lock (domain);
747 table = domain->jit_info_table;
749 ++mono_stats.jit_info_table_remove_count;
751 chunk_pos = jit_info_table_index (table, start);
752 g_assert (chunk_pos < table->num_chunks);
754 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
757 chunk = table->chunks [chunk_pos];
759 while (pos < chunk->num_elements) {
760 if (chunk->data [pos] == ji)
763 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
764 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
765 <= (guint8*)ji->code_start + ji->code_size);
772 } while (chunk_pos < table->num_chunks);
775 g_assert (chunk->data [pos] == ji);
777 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
779 /* Debugging code, should be removed. */
780 //jit_info_table_check (table);
782 mono_domain_unlock (domain);
785 static MonoAotModuleInfoTable*
786 mono_aot_module_info_table_new (void)
788 return g_array_new (FALSE, FALSE, sizeof (gpointer));
792 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
794 int left = 0, right = table->len;
796 while (left < right) {
797 int pos = (left + right) / 2;
798 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
799 char *start = ainfo->start;
800 char *end = ainfo->end;
804 else if (addr >= end)
814 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
816 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
819 ainfo->image = image;
820 ainfo->start = start;
823 mono_appdomains_lock ();
826 aot_modules = mono_aot_module_info_table_new ();
828 pos = aot_info_table_index (aot_modules, start);
830 g_array_insert_val (aot_modules, pos, ainfo);
832 mono_appdomains_unlock ();
836 mono_jit_info_find_aot_module (guint8* addr)
838 guint left = 0, right;
843 mono_appdomains_lock ();
845 right = aot_modules->len;
846 while (left < right) {
847 guint pos = (left + right) / 2;
848 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
850 if (addr < (guint8*)ai->start)
852 else if (addr >= (guint8*)ai->end)
855 mono_appdomains_unlock ();
860 mono_appdomains_unlock ();
866 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
868 jit_info_find_in_aot_func = func;
872 mono_jit_info_get_code_start (MonoJitInfo* ji)
874 return ji->code_start;
878 mono_jit_info_get_code_size (MonoJitInfo* ji)
880 return ji->code_size;
884 mono_jit_info_get_method (MonoJitInfo* ji)
890 jit_info_key_extract (gpointer value)
892 MonoJitInfo *info = (MonoJitInfo*)value;
898 jit_info_next_value (gpointer value)
900 MonoJitInfo *info = (MonoJitInfo*)value;
902 return (gpointer*)&info->next_jit_code_hash;
906 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
908 mono_internal_hash_table_init (jit_code_hash,
909 mono_aligned_addr_hash,
910 jit_info_key_extract,
911 jit_info_next_value);
915 * mono_jit_info_get_generic_sharing_context:
918 * Returns the jit info's generic sharing context, or NULL if it
921 MonoGenericSharingContext*
922 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
924 if (ji->has_generic_sharing_context)
925 return *((MonoGenericSharingContext**)&ji->clauses [ji->num_clauses]);
931 * mono_jit_info_set_generic_sharing_context:
933 * @gsctx: a generic sharing context
935 * Sets the jit info's generic sharing context. The jit info must
936 * have memory allocated for the context.
939 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
941 g_assert (ji->has_generic_sharing_context);
943 *((MonoGenericSharingContext**)&ji->clauses [ji->num_clauses]) = gsctx;
948 * @s1: First string to compare
949 * @s2: Second string to compare
951 * Returns FALSE if the strings differ.
954 mono_string_equal (MonoString *s1, MonoString *s2)
956 int l1 = mono_string_length (s1);
957 int l2 = mono_string_length (s2);
964 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
969 * @s: the string to hash
971 * Returns the hash for the string.
974 mono_string_hash (MonoString *s)
976 const guint16 *p = mono_string_chars (s);
977 int i, len = mono_string_length (s);
980 for (i = 0; i < len; i++) {
981 h = (h << 5) - h + *p;
989 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
991 int len = GPOINTER_TO_INT (s1 [0]);
992 if (len != GPOINTER_TO_INT (s2 [0]))
995 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
999 mono_ptrarray_hash (gpointer *s)
1002 int len = GPOINTER_TO_INT (s [0]);
1005 for (i = 1; i < len; i++)
1006 hash += GPOINTER_TO_UINT (s [i]);
1012 * Allocate an id for domain and set domain->domain_id.
1013 * LOCKING: must be called while holding appdomains_mutex.
1014 * We try to assign low numbers to the domain, so it can be used
1015 * as an index in data tables to lookup domain-specific info
1016 * with minimal memory overhead. We also try not to reuse the
1017 * same id too quickly (to help debugging).
1020 domain_id_alloc (MonoDomain *domain)
1023 if (!appdomains_list) {
1024 appdomain_list_size = 2;
1025 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1027 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1028 if (!appdomains_list [i]) {
1034 for (i = 0; i < appdomain_next; ++i) {
1035 if (!appdomains_list [i]) {
1042 MonoDomain **new_list;
1043 int new_size = appdomain_list_size * 2;
1044 if (new_size >= (1 << 16))
1045 g_assert_not_reached ();
1046 id = appdomain_list_size;
1047 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1048 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1049 mono_gc_free_fixed (appdomains_list);
1050 appdomains_list = new_list;
1051 appdomain_list_size = new_size;
1053 domain->domain_id = id;
1054 appdomains_list [id] = domain;
1056 if (appdomain_next > appdomain_list_size)
1061 static guint32 domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1062 static gpointer domain_gc_desc = NULL;
1063 static guint32 domain_shadow_serial = 0L;
1066 mono_domain_create (void)
1069 guint32 shadow_serial;
1071 mono_appdomains_lock ();
1072 shadow_serial = domain_shadow_serial++;
1074 if (!domain_gc_desc) {
1075 unsigned int i, bit = 0;
1076 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1077 bit = i / sizeof (gpointer);
1078 domain_gc_bitmap [bit / 32] |= 1 << (bit % 32);
1080 domain_gc_desc = mono_gc_make_descr_from_bitmap (domain_gc_bitmap, bit + 1);
1082 mono_appdomains_unlock ();
1084 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1085 domain->shadow_serial = shadow_serial;
1086 domain->domain = NULL;
1087 domain->setup = NULL;
1088 domain->friendly_name = NULL;
1089 domain->search_path = NULL;
1091 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1093 domain->mp = mono_mempool_new ();
1094 domain->code_mp = mono_code_manager_new ();
1095 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1096 domain->domain_assemblies = NULL;
1097 domain->class_vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1098 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1099 domain->static_data_array = NULL;
1100 mono_jit_code_hash_init (&domain->jit_code_hash);
1101 domain->ldstr_table = mono_g_hash_table_new ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal);
1102 domain->jit_info_table = jit_info_table_new ();
1103 domain->class_init_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1104 domain->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1105 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1106 domain->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1107 domain->delegate_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1109 InitializeCriticalSection (&domain->lock);
1110 InitializeCriticalSection (&domain->assemblies_lock);
1112 domain->shared_generics_hash = NULL;
1114 mono_debug_domain_create (domain);
1116 mono_appdomains_lock ();
1117 domain_id_alloc (domain);
1118 mono_appdomains_unlock ();
1120 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1126 * mono_init_internal:
1128 * Creates the initial application domain and initializes the mono_defaults
1130 * This function is guaranteed to not run any IL code.
1131 * If exe_filename is not NULL, the method will determine the required runtime
1132 * from the exe configuration file or the version PE field.
1133 * If runtime_version is not NULL, that runtime version will be used.
1134 * Either exe_filename or runtime_version must be provided.
1136 * Returns: the initial domain.
1139 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1141 static MonoDomain *domain = NULL;
1142 MonoAssembly *ass = NULL;
1143 MonoImageOpenStatus status = MONO_IMAGE_OK;
1144 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1148 g_assert_not_reached ();
1150 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1151 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1152 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1154 mono_gc_base_init ();
1156 appdomain_thread_id = TlsAlloc ();
1158 InitializeCriticalSection (&appdomains_mutex);
1160 mono_metadata_init ();
1161 mono_raw_buffer_init ();
1162 mono_images_init ();
1163 mono_assemblies_init ();
1164 mono_classes_init ();
1165 mono_loader_init ();
1166 mono_reflection_init ();
1168 /* FIXME: When should we release this memory? */
1169 MONO_GC_REGISTER_ROOT (appdomains_list);
1171 domain = mono_domain_create ();
1172 mono_root_domain = domain;
1174 SET_APPDOMAIN (domain);
1176 /* Get a list of runtimes supported by the exe */
1177 if (exe_filename != NULL) {
1179 * This function will load the exe file as a MonoImage. We need to close it, but
1180 * that would mean it would be reloaded later. So instead, we save it to
1181 * exe_image, and close it during shutdown.
1183 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1184 } else if (runtime_version != NULL) {
1185 runtimes [0] = get_runtime_by_version (runtime_version);
1186 runtimes [1] = NULL;
1189 if (runtimes [0] == NULL) {
1190 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1191 runtimes [0] = default_runtime;
1192 runtimes [1] = NULL;
1193 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1194 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1197 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1198 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1199 current_runtime = runtimes [n];
1200 ass = mono_assembly_load_corlib (current_runtime, &status);
1201 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1206 /* Now that we have a runtime, set the policy for unhandled exceptions */
1207 if (mono_get_runtime_info ()->framework_version [0] < '2') {
1208 mono_runtime_unhandled_exception_policy_set (MONO_UNHANLED_POLICY_LEGACY);
1211 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1213 case MONO_IMAGE_ERROR_ERRNO: {
1214 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1215 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1216 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1217 g_free (corlib_file);
1220 case MONO_IMAGE_IMAGE_INVALID:
1221 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1222 mono_assembly_getrootdir ());
1224 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1225 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1226 mono_assembly_getrootdir ());
1229 /* to suppress compiler warning */
1235 mono_defaults.corlib = mono_assembly_get_image (ass);
1237 mono_defaults.object_class = mono_class_from_name (
1238 mono_defaults.corlib, "System", "Object");
1239 g_assert (mono_defaults.object_class != 0);
1241 mono_defaults.void_class = mono_class_from_name (
1242 mono_defaults.corlib, "System", "Void");
1243 g_assert (mono_defaults.void_class != 0);
1245 mono_defaults.boolean_class = mono_class_from_name (
1246 mono_defaults.corlib, "System", "Boolean");
1247 g_assert (mono_defaults.boolean_class != 0);
1249 mono_defaults.byte_class = mono_class_from_name (
1250 mono_defaults.corlib, "System", "Byte");
1251 g_assert (mono_defaults.byte_class != 0);
1253 mono_defaults.sbyte_class = mono_class_from_name (
1254 mono_defaults.corlib, "System", "SByte");
1255 g_assert (mono_defaults.sbyte_class != 0);
1257 mono_defaults.int16_class = mono_class_from_name (
1258 mono_defaults.corlib, "System", "Int16");
1259 g_assert (mono_defaults.int16_class != 0);
1261 mono_defaults.uint16_class = mono_class_from_name (
1262 mono_defaults.corlib, "System", "UInt16");
1263 g_assert (mono_defaults.uint16_class != 0);
1265 mono_defaults.int32_class = mono_class_from_name (
1266 mono_defaults.corlib, "System", "Int32");
1267 g_assert (mono_defaults.int32_class != 0);
1269 mono_defaults.uint32_class = mono_class_from_name (
1270 mono_defaults.corlib, "System", "UInt32");
1271 g_assert (mono_defaults.uint32_class != 0);
1273 mono_defaults.uint_class = mono_class_from_name (
1274 mono_defaults.corlib, "System", "UIntPtr");
1275 g_assert (mono_defaults.uint_class != 0);
1277 mono_defaults.int_class = mono_class_from_name (
1278 mono_defaults.corlib, "System", "IntPtr");
1279 g_assert (mono_defaults.int_class != 0);
1281 mono_defaults.int64_class = mono_class_from_name (
1282 mono_defaults.corlib, "System", "Int64");
1283 g_assert (mono_defaults.int64_class != 0);
1285 mono_defaults.uint64_class = mono_class_from_name (
1286 mono_defaults.corlib, "System", "UInt64");
1287 g_assert (mono_defaults.uint64_class != 0);
1289 mono_defaults.single_class = mono_class_from_name (
1290 mono_defaults.corlib, "System", "Single");
1291 g_assert (mono_defaults.single_class != 0);
1293 mono_defaults.double_class = mono_class_from_name (
1294 mono_defaults.corlib, "System", "Double");
1295 g_assert (mono_defaults.double_class != 0);
1297 mono_defaults.char_class = mono_class_from_name (
1298 mono_defaults.corlib, "System", "Char");
1299 g_assert (mono_defaults.char_class != 0);
1301 mono_defaults.string_class = mono_class_from_name (
1302 mono_defaults.corlib, "System", "String");
1303 g_assert (mono_defaults.string_class != 0);
1305 mono_defaults.enum_class = mono_class_from_name (
1306 mono_defaults.corlib, "System", "Enum");
1307 g_assert (mono_defaults.enum_class != 0);
1309 mono_defaults.array_class = mono_class_from_name (
1310 mono_defaults.corlib, "System", "Array");
1311 g_assert (mono_defaults.array_class != 0);
1313 mono_defaults.delegate_class = mono_class_from_name (
1314 mono_defaults.corlib, "System", "Delegate");
1315 g_assert (mono_defaults.delegate_class != 0 );
1317 mono_defaults.multicastdelegate_class = mono_class_from_name (
1318 mono_defaults.corlib, "System", "MulticastDelegate");
1319 g_assert (mono_defaults.multicastdelegate_class != 0 );
1321 mono_defaults.asyncresult_class = mono_class_from_name (
1322 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1324 g_assert (mono_defaults.asyncresult_class != 0 );
1326 mono_defaults.waithandle_class = mono_class_from_name (
1327 mono_defaults.corlib, "System.Threading", "WaitHandle");
1328 g_assert (mono_defaults.waithandle_class != 0 );
1330 mono_defaults.typehandle_class = mono_class_from_name (
1331 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1332 g_assert (mono_defaults.typehandle_class != 0);
1334 mono_defaults.methodhandle_class = mono_class_from_name (
1335 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1336 g_assert (mono_defaults.methodhandle_class != 0);
1338 mono_defaults.fieldhandle_class = mono_class_from_name (
1339 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1340 g_assert (mono_defaults.fieldhandle_class != 0);
1342 mono_defaults.systemtype_class = mono_class_from_name (
1343 mono_defaults.corlib, "System", "Type");
1344 g_assert (mono_defaults.systemtype_class != 0);
1346 mono_defaults.monotype_class = mono_class_from_name (
1347 mono_defaults.corlib, "System", "MonoType");
1348 g_assert (mono_defaults.monotype_class != 0);
1350 mono_defaults.exception_class = mono_class_from_name (
1351 mono_defaults.corlib, "System", "Exception");
1352 g_assert (mono_defaults.exception_class != 0);
1354 mono_defaults.threadabortexception_class = mono_class_from_name (
1355 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1356 g_assert (mono_defaults.threadabortexception_class != 0);
1358 mono_defaults.thread_class = mono_class_from_name (
1359 mono_defaults.corlib, "System.Threading", "Thread");
1360 g_assert (mono_defaults.thread_class != 0);
1362 mono_defaults.appdomain_class = mono_class_from_name (
1363 mono_defaults.corlib, "System", "AppDomain");
1364 g_assert (mono_defaults.appdomain_class != 0);
1366 mono_defaults.transparent_proxy_class = mono_class_from_name (
1367 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1368 g_assert (mono_defaults.transparent_proxy_class != 0);
1370 mono_defaults.real_proxy_class = mono_class_from_name (
1371 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1372 g_assert (mono_defaults.real_proxy_class != 0);
1374 mono_defaults.mono_method_message_class = mono_class_from_name (
1375 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1376 g_assert (mono_defaults.mono_method_message_class != 0);
1378 mono_defaults.field_info_class = mono_class_from_name (
1379 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1380 g_assert (mono_defaults.field_info_class != 0);
1382 mono_defaults.method_info_class = mono_class_from_name (
1383 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1384 g_assert (mono_defaults.method_info_class != 0);
1386 mono_defaults.stringbuilder_class = mono_class_from_name (
1387 mono_defaults.corlib, "System.Text", "StringBuilder");
1388 g_assert (mono_defaults.stringbuilder_class != 0);
1390 mono_defaults.math_class = mono_class_from_name (
1391 mono_defaults.corlib, "System", "Math");
1392 g_assert (mono_defaults.math_class != 0);
1394 mono_defaults.stack_frame_class = mono_class_from_name (
1395 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1396 g_assert (mono_defaults.stack_frame_class != 0);
1398 mono_defaults.stack_trace_class = mono_class_from_name (
1399 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1400 g_assert (mono_defaults.stack_trace_class != 0);
1402 mono_defaults.marshal_class = mono_class_from_name (
1403 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1404 g_assert (mono_defaults.marshal_class != 0);
1406 mono_defaults.iserializeable_class = mono_class_from_name (
1407 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1408 g_assert (mono_defaults.iserializeable_class != 0);
1410 mono_defaults.serializationinfo_class = mono_class_from_name (
1411 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1412 g_assert (mono_defaults.serializationinfo_class != 0);
1414 mono_defaults.streamingcontext_class = mono_class_from_name (
1415 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1416 g_assert (mono_defaults.streamingcontext_class != 0);
1418 mono_defaults.typed_reference_class = mono_class_from_name (
1419 mono_defaults.corlib, "System", "TypedReference");
1420 g_assert (mono_defaults.typed_reference_class != 0);
1422 mono_defaults.argumenthandle_class = mono_class_from_name (
1423 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1424 g_assert (mono_defaults.argumenthandle_class != 0);
1426 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1427 mono_defaults.corlib, "System", "MarshalByRefObject");
1428 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1430 mono_defaults.monitor_class = mono_class_from_name (
1431 mono_defaults.corlib, "System.Threading", "Monitor");
1432 g_assert (mono_defaults.monitor_class != 0);
1434 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1435 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1436 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1438 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1439 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1441 mono_defaults.executioncontext_class = mono_class_from_name (
1442 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1444 mono_defaults.internals_visible_class = mono_class_from_name (
1445 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1448 * mscorlib needs a little help, only now it can load its friends list (after we have
1449 * loaded the InternalsVisibleToAttribute), load it now
1451 mono_assembly_load_friends (ass);
1453 mono_defaults.safehandle_class = mono_class_from_name (
1454 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1456 mono_defaults.handleref_class = mono_class_from_name (
1457 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1459 mono_defaults.attribute_class = mono_class_from_name (
1460 mono_defaults.corlib, "System", "Attribute");
1462 mono_defaults.customattribute_data_class = mono_class_from_name (
1463 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1465 /* these are initialized lazily when COM features are used */
1466 mono_defaults.variant_class = NULL;
1467 mono_defaults.com_object_class = NULL;
1468 mono_defaults.com_interop_proxy_class = NULL;
1469 mono_defaults.iunknown_class = NULL;
1470 mono_defaults.idispatch_class = NULL;
1473 * Note that mono_defaults.generic_*_class is only non-NULL if we're
1474 * using the 2.0 corlib.
1476 mono_class_init (mono_defaults.array_class);
1477 mono_defaults.generic_nullable_class = mono_class_from_name (
1478 mono_defaults.corlib, "System", "Nullable`1");
1479 mono_defaults.generic_ilist_class = mono_class_from_name (
1480 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1482 domain->friendly_name = g_path_get_basename (filename);
1484 _mono_debug_init_corlib (domain);
1492 * Creates the initial application domain and initializes the mono_defaults
1494 * This function is guaranteed to not run any IL code.
1495 * The runtime is initialized using the default runtime version.
1497 * Returns: the initial domain.
1500 mono_init (const char *domain_name)
1502 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1506 * mono_init_from_assembly:
1508 * Creates the initial application domain and initializes the mono_defaults
1510 * This function is guaranteed to not run any IL code.
1511 * The runtime is initialized using the runtime version required by the
1512 * provided executable. The version is determined by looking at the exe
1513 * configuration file and the version PE field)
1515 * Returns: the initial domain.
1518 mono_init_from_assembly (const char *domain_name, const char *filename)
1520 return mono_init_internal (domain_name, filename, NULL);
1524 * mono_init_version:
1526 * Creates the initial application domain and initializes the mono_defaults
1528 * This function is guaranteed to not run any IL code.
1529 * The runtime is initialized using the provided rutime version.
1531 * Returns: the initial domain.
1534 mono_init_version (const char *domain_name, const char *version)
1536 return mono_init_internal (domain_name, NULL, version);
1540 * mono_init_com_types:
1542 * Initializes all types needed for COM Interop in mono_defaults structure.
1545 mono_init_com_types (void)
1547 static gboolean initialized = FALSE;
1552 /* FIXME: do I need some threading protection here */
1554 g_assert (mono_defaults.corlib);
1556 mono_defaults.variant_class = mono_class_from_name (
1557 mono_defaults.corlib, "System", "Variant");
1558 g_assert (mono_defaults.variant_class != 0);
1560 mono_defaults.com_object_class = mono_class_from_name (
1561 mono_defaults.corlib, "System", "__ComObject");
1562 g_assert (mono_defaults.com_object_class != 0);
1564 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1565 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1566 g_assert (mono_defaults.com_interop_proxy_class != 0);
1568 mono_defaults.iunknown_class = mono_class_from_name (
1569 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1570 g_assert (mono_defaults.iunknown_class != 0);
1572 mono_defaults.idispatch_class = mono_class_from_name (
1573 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1574 g_assert (mono_defaults.idispatch_class != 0);
1582 * Cleans up all metadata modules.
1588 mono_image_close (exe_image);
1590 mono_loader_cleanup ();
1591 mono_classes_cleanup ();
1592 mono_assemblies_cleanup ();
1593 mono_images_cleanup ();
1594 mono_debug_cleanup ();
1595 mono_raw_buffer_cleanup ();
1596 mono_metadata_cleanup ();
1598 TlsFree (appdomain_thread_id);
1599 DeleteCriticalSection (&appdomains_mutex);
1603 * mono_get_root_domain:
1605 * The root AppDomain is the initial domain created by the runtime when it is
1606 * initialized. Programs execute on this AppDomain, but can create new ones
1607 * later. Currently there is no unmanaged API to create new AppDomains, this
1608 * must be done from managed code.
1610 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1613 mono_get_root_domain (void)
1615 return mono_root_domain;
1621 * Returns: the current domain, to obtain the root domain use
1622 * mono_get_root_domain().
1627 return GET_APPDOMAIN ();
1631 * mono_domain_set_internal:
1632 * @domain: the new domain
1634 * Sets the current domain to @domain.
1637 mono_domain_set_internal (MonoDomain *domain)
1639 SET_APPDOMAIN (domain);
1640 SET_APPCONTEXT (domain->default_context);
1644 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1650 * Create a copy of the data to avoid calling the user callback
1651 * inside the lock because that could lead to deadlocks.
1652 * We can do this because this function is not perf. critical.
1654 mono_appdomains_lock ();
1655 size = appdomain_list_size;
1656 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1657 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1658 mono_appdomains_unlock ();
1660 for (i = 0; i < size; ++i) {
1662 func (copy [i], user_data);
1665 mono_gc_free_fixed (copy);
1669 * mono_domain_assembly_open:
1670 * @domain: the application domain
1671 * @name: file name of the assembly
1673 * fixme: maybe we should integrate this with mono_assembly_open ??
1676 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1681 mono_domain_assemblies_lock (domain);
1682 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1684 if (strcmp (name, ass->aname.name) == 0) {
1685 mono_domain_assemblies_unlock (domain);
1689 mono_domain_assemblies_unlock (domain);
1691 if (!(ass = mono_assembly_open (name, NULL)))
1698 mono_domain_lookup_shared_generic (MonoDomain *domain, MonoMethod *method)
1700 if (!domain->shared_generics_hash)
1703 return g_hash_table_lookup (domain->shared_generics_hash, method);
1707 mono_domain_register_shared_generic (MonoDomain *domain, MonoMethod *method, MonoJitInfo *jit_info)
1709 if (!domain->shared_generics_hash)
1710 domain->shared_generics_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1712 g_assert (domain->shared_generics_hash);
1714 g_hash_table_insert (domain->shared_generics_hash, method, jit_info);
1718 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
1720 MonoJitDynamicMethodInfo *di = value;
1721 mono_code_manager_destroy (di->code_mp);
1726 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
1728 g_slist_free (value);
1732 mono_domain_free (MonoDomain *domain, gboolean force)
1734 int code_size, code_alloc;
1736 if ((domain == mono_root_domain) && !force) {
1737 g_warning ("cant unload root domain");
1741 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1743 mono_debug_domain_unload (domain);
1745 mono_appdomains_lock ();
1746 appdomains_list [domain->domain_id] = NULL;
1747 mono_appdomains_unlock ();
1749 /* FIXME: free delegate_hash_table when it's used */
1750 if (domain->search_path) {
1751 g_strfreev (domain->search_path);
1752 domain->search_path = NULL;
1754 domain->create_proxy_for_type_method = NULL;
1755 domain->private_invoke_method = NULL;
1756 domain->default_context = NULL;
1757 domain->out_of_memory_ex = NULL;
1758 domain->null_reference_ex = NULL;
1759 domain->stack_overflow_ex = NULL;
1760 domain->entry_assembly = NULL;
1761 /* must do this early as it accesses fields and types */
1762 if (domain->special_static_fields) {
1763 mono_alloc_special_static_data_free (domain->special_static_fields);
1764 g_hash_table_destroy (domain->special_static_fields);
1765 domain->special_static_fields = NULL;
1767 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1768 MonoAssembly *ass = tmp->data;
1769 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);
1770 mono_assembly_close (ass);
1772 g_slist_free (domain->domain_assemblies);
1773 domain->domain_assemblies = NULL;
1775 g_free (domain->friendly_name);
1776 domain->friendly_name = NULL;
1777 mono_g_hash_table_destroy (domain->env);
1779 g_hash_table_destroy (domain->class_vtable_hash);
1780 domain->class_vtable_hash = NULL;
1781 g_hash_table_destroy (domain->proxy_vtable_hash);
1782 domain->proxy_vtable_hash = NULL;
1783 if (domain->static_data_array) {
1784 mono_gc_free_fixed (domain->static_data_array);
1785 domain->static_data_array = NULL;
1787 mono_internal_hash_table_destroy (&domain->jit_code_hash);
1788 if (domain->dynamic_code_hash) {
1789 g_hash_table_foreach (domain->dynamic_code_hash, dynamic_method_info_free, NULL);
1790 g_hash_table_destroy (domain->dynamic_code_hash);
1791 domain->dynamic_code_hash = NULL;
1793 mono_g_hash_table_destroy (domain->ldstr_table);
1794 domain->ldstr_table = NULL;
1795 jit_info_table_free (domain->jit_info_table);
1796 domain->jit_info_table = NULL;
1798 /* collect statistics */
1799 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
1800 total_domain_code_alloc += code_alloc;
1801 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
1802 max_domain_code_size = MAX (max_domain_code_size, code_size);
1804 #ifdef DEBUG_DOMAIN_UNLOAD
1805 mono_mempool_invalidate (domain->mp);
1806 mono_code_manager_invalidate (domain->code_mp);
1808 mono_mempool_destroy (domain->mp);
1810 mono_code_manager_destroy (domain->code_mp);
1811 domain->code_mp = NULL;
1813 if (domain->jump_target_hash) {
1814 g_hash_table_foreach (domain->jump_target_hash, delete_jump_list, NULL);
1815 g_hash_table_destroy (domain->jump_target_hash);
1816 domain->jump_target_hash = NULL;
1818 if (domain->type_hash) {
1819 mono_g_hash_table_destroy (domain->type_hash);
1820 domain->type_hash = NULL;
1822 if (domain->refobject_hash) {
1823 mono_g_hash_table_destroy (domain->refobject_hash);
1824 domain->refobject_hash = NULL;
1826 if (domain->type_init_exception_hash) {
1827 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1828 domain->type_init_exception_hash = NULL;
1830 g_hash_table_destroy (domain->class_init_trampoline_hash);
1831 domain->class_init_trampoline_hash = NULL;
1832 g_hash_table_destroy (domain->jump_trampoline_hash);
1833 domain->jump_trampoline_hash = NULL;
1834 g_hash_table_destroy (domain->finalizable_objects_hash);
1835 domain->finalizable_objects_hash = NULL;
1836 g_hash_table_destroy (domain->jit_trampoline_hash);
1837 domain->jit_trampoline_hash = NULL;
1838 g_hash_table_destroy (domain->delegate_trampoline_hash);
1839 domain->delegate_trampoline_hash = NULL;
1840 if (domain->shared_generics_hash) {
1841 g_hash_table_destroy (domain->shared_generics_hash);
1842 domain->shared_generics_hash = NULL;
1845 DeleteCriticalSection (&domain->assemblies_lock);
1846 DeleteCriticalSection (&domain->lock);
1847 domain->setup = NULL;
1849 /* FIXME: anything else required ? */
1851 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
1853 mono_gc_free_fixed (domain);
1855 if ((domain == mono_root_domain))
1856 mono_root_domain = NULL;
1860 * mono_domain_get_id:
1863 * Returns: the a domain for a specific domain id.
1866 mono_domain_get_by_id (gint32 domainid)
1868 MonoDomain * domain;
1870 mono_appdomains_lock ();
1871 if (domainid < appdomain_list_size)
1872 domain = appdomains_list [domainid];
1875 mono_appdomains_unlock ();
1881 mono_domain_get_id (MonoDomain *domain)
1883 return domain->domain_id;
1887 mono_context_set (MonoAppContext * new_context)
1889 SET_APPCONTEXT (new_context);
1893 mono_context_get (void)
1895 return GET_APPCONTEXT ();
1898 /* LOCKING: the caller holds the lock for this domain */
1900 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
1902 /* The first entry in the array is the index of the next free slot
1903 * and the total size of the array
1906 if (domain->static_data_array) {
1907 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
1908 next = GPOINTER_TO_INT (domain->static_data_array [0]);
1910 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), NULL);
1911 memcpy (new_array, domain->static_data_array, sizeof (gpointer) * size);
1913 new_array [1] = GINT_TO_POINTER (size);
1914 mono_gc_free_fixed (domain->static_data_array);
1915 domain->static_data_array = new_array;
1919 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, NULL);
1921 new_array [0] = GINT_TO_POINTER (next);
1922 new_array [1] = GINT_TO_POINTER (size);
1923 domain->static_data_array = new_array;
1925 domain->static_data_array [next++] = data;
1926 domain->static_data_array [0] = GINT_TO_POINTER (next);
1930 mono_get_corlib (void)
1932 return mono_defaults.corlib;
1936 mono_get_object_class (void)
1938 return mono_defaults.object_class;
1942 mono_get_byte_class (void)
1944 return mono_defaults.byte_class;
1948 mono_get_void_class (void)
1950 return mono_defaults.void_class;
1954 mono_get_boolean_class (void)
1956 return mono_defaults.boolean_class;
1960 mono_get_sbyte_class (void)
1962 return mono_defaults.sbyte_class;
1966 mono_get_int16_class (void)
1968 return mono_defaults.int16_class;
1972 mono_get_uint16_class (void)
1974 return mono_defaults.uint16_class;
1978 mono_get_int32_class (void)
1980 return mono_defaults.int32_class;
1984 mono_get_uint32_class (void)
1986 return mono_defaults.uint32_class;
1990 mono_get_intptr_class (void)
1992 return mono_defaults.int_class;
1996 mono_get_uintptr_class (void)
1998 return mono_defaults.uint_class;
2002 mono_get_int64_class (void)
2004 return mono_defaults.int64_class;
2008 mono_get_uint64_class (void)
2010 return mono_defaults.uint64_class;
2014 mono_get_single_class (void)
2016 return mono_defaults.single_class;
2020 mono_get_double_class (void)
2022 return mono_defaults.double_class;
2026 mono_get_char_class (void)
2028 return mono_defaults.char_class;
2032 mono_get_string_class (void)
2034 return mono_defaults.string_class;
2038 mono_get_enum_class (void)
2040 return mono_defaults.enum_class;
2044 mono_get_array_class (void)
2046 return mono_defaults.array_class;
2050 mono_get_thread_class (void)
2052 return mono_defaults.thread_class;
2056 mono_get_exception_class (void)
2058 return mono_defaults.exception_class;
2062 static char* get_attribute_value (const gchar **attribute_names,
2063 const gchar **attribute_values,
2064 const char *att_name)
2067 for (n=0; attribute_names[n] != NULL; n++) {
2068 if (strcmp (attribute_names[n], att_name) == 0)
2069 return g_strdup (attribute_values[n]);
2074 static void start_element (GMarkupParseContext *context,
2075 const gchar *element_name,
2076 const gchar **attribute_names,
2077 const gchar **attribute_values,
2081 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2083 if (strcmp (element_name, "configuration") == 0) {
2084 app_config->configuration_count++;
2087 if (strcmp (element_name, "startup") == 0) {
2088 app_config->startup_count++;
2092 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2095 if (strcmp (element_name, "requiredRuntime") == 0) {
2096 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2097 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2098 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2099 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2103 static void end_element (GMarkupParseContext *context,
2104 const gchar *element_name,
2108 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2110 if (strcmp (element_name, "configuration") == 0) {
2111 app_config->configuration_count--;
2112 } else if (strcmp (element_name, "startup") == 0) {
2113 app_config->startup_count--;
2117 static const GMarkupParser
2126 static AppConfigInfo *
2127 app_config_parse (const char *exe_filename)
2129 AppConfigInfo *app_config;
2130 GMarkupParseContext *context;
2134 const char *bundled_config;
2135 char *config_filename;
2137 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2139 if (bundled_config) {
2140 text = g_strdup (bundled_config);
2141 len = strlen (text);
2143 config_filename = g_strconcat (exe_filename, ".config", NULL);
2145 if (stat (config_filename, &buf) != 0) {
2146 g_free (config_filename);
2150 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2151 g_free (config_filename);
2154 g_free (config_filename);
2157 app_config = g_new0 (AppConfigInfo, 1);
2159 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2160 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2161 g_markup_parse_context_end_parse (context, NULL);
2163 g_markup_parse_context_free (context);
2169 app_config_free (AppConfigInfo* app_config)
2172 GSList *list = app_config->supported_runtimes;
2173 while (list != NULL) {
2174 rt = (char*)list->data;
2176 list = g_slist_next (list);
2178 g_slist_free (app_config->supported_runtimes);
2179 g_free (app_config->required_runtime);
2180 g_free (app_config);
2184 static const MonoRuntimeInfo*
2185 get_runtime_by_version (const char *version)
2188 int max = G_N_ELEMENTS (supported_runtimes);
2190 for (n=0; n<max; n++) {
2191 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2192 return &supported_runtimes[n];
2198 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2200 AppConfigInfo* app_config;
2202 const MonoRuntimeInfo* runtime = NULL;
2203 MonoImage *image = NULL;
2205 app_config = app_config_parse (exe_file);
2207 if (app_config != NULL) {
2208 /* Check supportedRuntime elements, if none is supported, fail.
2209 * If there are no such elements, look for a requiredRuntime element.
2211 if (app_config->supported_runtimes != NULL) {
2213 GSList *list = app_config->supported_runtimes;
2214 while (list != NULL) {
2215 version = (char*) list->data;
2216 runtime = get_runtime_by_version (version);
2217 if (runtime != NULL)
2218 runtimes [n++] = runtime;
2219 list = g_slist_next (list);
2221 runtimes [n] = NULL;
2222 app_config_free (app_config);
2226 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2227 if (app_config->required_runtime != NULL) {
2228 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2229 runtimes [1] = NULL;
2230 app_config_free (app_config);
2233 app_config_free (app_config);
2236 /* Look for a runtime with the exact version */
2237 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2240 image = mono_image_open (exe_file, NULL);
2242 if (image == NULL) {
2243 /* The image is wrong or the file was not found. In this case return
2244 * a default runtime and leave to the initialization method the work of
2245 * reporting the error.
2247 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2248 runtimes [1] = NULL;
2254 runtimes [0] = get_runtime_by_version (image->version);
2255 runtimes [1] = NULL;
2260 * mono_get_runtime_info:
2262 * Returns: the version of the current runtime instance.
2264 const MonoRuntimeInfo*
2265 mono_get_runtime_info (void)
2267 return current_runtime;
2271 mono_debugger_check_runtime_version (const char *filename)
2273 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2274 const MonoRuntimeInfo *rinfo;
2277 get_runtimes_from_exe (filename, &image, runtimes);
2278 rinfo = runtimes [0];
2281 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2283 if (rinfo != current_runtime)
2284 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2285 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2286 filename, rinfo->runtime_version);