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,0,5,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);
405 static G_GNUC_UNUSED void
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_jit_info (MonoJitInfo *ji)
917 if (ji->has_generic_jit_info)
918 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
924 * mono_jit_info_get_generic_sharing_context:
927 * Returns the jit info's generic sharing context, or NULL if it
930 MonoGenericSharingContext*
931 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
933 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
936 return gi->generic_sharing_context;
942 * mono_jit_info_set_generic_sharing_context:
944 * @gsctx: a generic sharing context
946 * Sets the jit info's generic sharing context. The jit info must
947 * have memory allocated for the context.
950 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
952 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
956 gi->generic_sharing_context = gsctx;
961 * @s1: First string to compare
962 * @s2: Second string to compare
964 * Returns FALSE if the strings differ.
967 mono_string_equal (MonoString *s1, MonoString *s2)
969 int l1 = mono_string_length (s1);
970 int l2 = mono_string_length (s2);
977 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
982 * @s: the string to hash
984 * Returns the hash for the string.
987 mono_string_hash (MonoString *s)
989 const guint16 *p = mono_string_chars (s);
990 int i, len = mono_string_length (s);
993 for (i = 0; i < len; i++) {
994 h = (h << 5) - h + *p;
1002 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1004 int len = GPOINTER_TO_INT (s1 [0]);
1005 if (len != GPOINTER_TO_INT (s2 [0]))
1008 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1012 mono_ptrarray_hash (gpointer *s)
1015 int len = GPOINTER_TO_INT (s [0]);
1018 for (i = 1; i < len; i++)
1019 hash += GPOINTER_TO_UINT (s [i]);
1025 * Allocate an id for domain and set domain->domain_id.
1026 * LOCKING: must be called while holding appdomains_mutex.
1027 * We try to assign low numbers to the domain, so it can be used
1028 * as an index in data tables to lookup domain-specific info
1029 * with minimal memory overhead. We also try not to reuse the
1030 * same id too quickly (to help debugging).
1033 domain_id_alloc (MonoDomain *domain)
1036 if (!appdomains_list) {
1037 appdomain_list_size = 2;
1038 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1040 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1041 if (!appdomains_list [i]) {
1047 for (i = 0; i < appdomain_next; ++i) {
1048 if (!appdomains_list [i]) {
1055 MonoDomain **new_list;
1056 int new_size = appdomain_list_size * 2;
1057 if (new_size >= (1 << 16))
1058 g_assert_not_reached ();
1059 id = appdomain_list_size;
1060 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1061 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1062 mono_gc_free_fixed (appdomains_list);
1063 appdomains_list = new_list;
1064 appdomain_list_size = new_size;
1066 domain->domain_id = id;
1067 appdomains_list [id] = domain;
1069 if (appdomain_next > appdomain_list_size)
1074 static guint32 domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1075 static gpointer domain_gc_desc = NULL;
1076 static guint32 domain_shadow_serial = 0L;
1079 mono_domain_create (void)
1082 guint32 shadow_serial;
1084 mono_appdomains_lock ();
1085 shadow_serial = domain_shadow_serial++;
1087 if (!domain_gc_desc) {
1088 unsigned int i, bit = 0;
1089 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1090 bit = i / sizeof (gpointer);
1091 domain_gc_bitmap [bit / 32] |= 1 << (bit % 32);
1093 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1095 mono_appdomains_unlock ();
1097 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1098 domain->shadow_serial = shadow_serial;
1099 domain->domain = NULL;
1100 domain->setup = NULL;
1101 domain->friendly_name = NULL;
1102 domain->search_path = NULL;
1104 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1106 domain->mp = mono_mempool_new ();
1107 domain->code_mp = mono_code_manager_new ();
1108 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1109 domain->domain_assemblies = NULL;
1110 domain->class_vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1111 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1112 domain->static_data_array = NULL;
1113 mono_jit_code_hash_init (&domain->jit_code_hash);
1114 domain->ldstr_table = mono_g_hash_table_new ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal);
1115 domain->jit_info_table = jit_info_table_new ();
1116 domain->class_init_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1117 domain->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1118 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1119 domain->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1120 domain->delegate_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1122 InitializeCriticalSection (&domain->lock);
1123 InitializeCriticalSection (&domain->assemblies_lock);
1125 domain->shared_generics_hash = NULL;
1127 mono_debug_domain_create (domain);
1129 mono_appdomains_lock ();
1130 domain_id_alloc (domain);
1131 mono_appdomains_unlock ();
1133 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1139 * mono_init_internal:
1141 * Creates the initial application domain and initializes the mono_defaults
1143 * This function is guaranteed to not run any IL code.
1144 * If exe_filename is not NULL, the method will determine the required runtime
1145 * from the exe configuration file or the version PE field.
1146 * If runtime_version is not NULL, that runtime version will be used.
1147 * Either exe_filename or runtime_version must be provided.
1149 * Returns: the initial domain.
1152 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1154 static MonoDomain *domain = NULL;
1155 MonoAssembly *ass = NULL;
1156 MonoImageOpenStatus status = MONO_IMAGE_OK;
1157 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1161 g_assert_not_reached ();
1163 mono_perfcounters_init ();
1165 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1166 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1167 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1169 mono_gc_base_init ();
1171 appdomain_thread_id = TlsAlloc ();
1173 InitializeCriticalSection (&appdomains_mutex);
1175 mono_metadata_init ();
1176 mono_raw_buffer_init ();
1177 mono_images_init ();
1178 mono_assemblies_init ();
1179 mono_classes_init ();
1180 mono_loader_init ();
1181 mono_reflection_init ();
1183 /* FIXME: When should we release this memory? */
1184 MONO_GC_REGISTER_ROOT (appdomains_list);
1186 domain = mono_domain_create ();
1187 mono_root_domain = domain;
1189 SET_APPDOMAIN (domain);
1191 /* Get a list of runtimes supported by the exe */
1192 if (exe_filename != NULL) {
1194 * This function will load the exe file as a MonoImage. We need to close it, but
1195 * that would mean it would be reloaded later. So instead, we save it to
1196 * exe_image, and close it during shutdown.
1198 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1199 } else if (runtime_version != NULL) {
1200 runtimes [0] = get_runtime_by_version (runtime_version);
1201 runtimes [1] = NULL;
1204 if (runtimes [0] == NULL) {
1205 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1206 runtimes [0] = default_runtime;
1207 runtimes [1] = NULL;
1208 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1209 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1212 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1213 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1214 current_runtime = runtimes [n];
1215 ass = mono_assembly_load_corlib (current_runtime, &status);
1216 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1221 /* Now that we have a runtime, set the policy for unhandled exceptions */
1222 if (mono_get_runtime_info ()->framework_version [0] < '2') {
1223 mono_runtime_unhandled_exception_policy_set (MONO_UNHANLED_POLICY_LEGACY);
1226 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1228 case MONO_IMAGE_ERROR_ERRNO: {
1229 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1230 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1231 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1232 g_free (corlib_file);
1235 case MONO_IMAGE_IMAGE_INVALID:
1236 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1237 mono_assembly_getrootdir ());
1239 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1240 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1241 mono_assembly_getrootdir ());
1244 /* to suppress compiler warning */
1250 mono_defaults.corlib = mono_assembly_get_image (ass);
1252 mono_defaults.object_class = mono_class_from_name (
1253 mono_defaults.corlib, "System", "Object");
1254 g_assert (mono_defaults.object_class != 0);
1256 mono_defaults.void_class = mono_class_from_name (
1257 mono_defaults.corlib, "System", "Void");
1258 g_assert (mono_defaults.void_class != 0);
1260 mono_defaults.boolean_class = mono_class_from_name (
1261 mono_defaults.corlib, "System", "Boolean");
1262 g_assert (mono_defaults.boolean_class != 0);
1264 mono_defaults.byte_class = mono_class_from_name (
1265 mono_defaults.corlib, "System", "Byte");
1266 g_assert (mono_defaults.byte_class != 0);
1268 mono_defaults.sbyte_class = mono_class_from_name (
1269 mono_defaults.corlib, "System", "SByte");
1270 g_assert (mono_defaults.sbyte_class != 0);
1272 mono_defaults.int16_class = mono_class_from_name (
1273 mono_defaults.corlib, "System", "Int16");
1274 g_assert (mono_defaults.int16_class != 0);
1276 mono_defaults.uint16_class = mono_class_from_name (
1277 mono_defaults.corlib, "System", "UInt16");
1278 g_assert (mono_defaults.uint16_class != 0);
1280 mono_defaults.int32_class = mono_class_from_name (
1281 mono_defaults.corlib, "System", "Int32");
1282 g_assert (mono_defaults.int32_class != 0);
1284 mono_defaults.uint32_class = mono_class_from_name (
1285 mono_defaults.corlib, "System", "UInt32");
1286 g_assert (mono_defaults.uint32_class != 0);
1288 mono_defaults.uint_class = mono_class_from_name (
1289 mono_defaults.corlib, "System", "UIntPtr");
1290 g_assert (mono_defaults.uint_class != 0);
1292 mono_defaults.int_class = mono_class_from_name (
1293 mono_defaults.corlib, "System", "IntPtr");
1294 g_assert (mono_defaults.int_class != 0);
1296 mono_defaults.int64_class = mono_class_from_name (
1297 mono_defaults.corlib, "System", "Int64");
1298 g_assert (mono_defaults.int64_class != 0);
1300 mono_defaults.uint64_class = mono_class_from_name (
1301 mono_defaults.corlib, "System", "UInt64");
1302 g_assert (mono_defaults.uint64_class != 0);
1304 mono_defaults.single_class = mono_class_from_name (
1305 mono_defaults.corlib, "System", "Single");
1306 g_assert (mono_defaults.single_class != 0);
1308 mono_defaults.double_class = mono_class_from_name (
1309 mono_defaults.corlib, "System", "Double");
1310 g_assert (mono_defaults.double_class != 0);
1312 mono_defaults.char_class = mono_class_from_name (
1313 mono_defaults.corlib, "System", "Char");
1314 g_assert (mono_defaults.char_class != 0);
1316 mono_defaults.string_class = mono_class_from_name (
1317 mono_defaults.corlib, "System", "String");
1318 g_assert (mono_defaults.string_class != 0);
1320 mono_defaults.enum_class = mono_class_from_name (
1321 mono_defaults.corlib, "System", "Enum");
1322 g_assert (mono_defaults.enum_class != 0);
1324 mono_defaults.array_class = mono_class_from_name (
1325 mono_defaults.corlib, "System", "Array");
1326 g_assert (mono_defaults.array_class != 0);
1328 mono_defaults.delegate_class = mono_class_from_name (
1329 mono_defaults.corlib, "System", "Delegate");
1330 g_assert (mono_defaults.delegate_class != 0 );
1332 mono_defaults.multicastdelegate_class = mono_class_from_name (
1333 mono_defaults.corlib, "System", "MulticastDelegate");
1334 g_assert (mono_defaults.multicastdelegate_class != 0 );
1336 mono_defaults.asyncresult_class = mono_class_from_name (
1337 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1339 g_assert (mono_defaults.asyncresult_class != 0 );
1341 mono_defaults.waithandle_class = mono_class_from_name (
1342 mono_defaults.corlib, "System.Threading", "WaitHandle");
1343 g_assert (mono_defaults.waithandle_class != 0 );
1345 mono_defaults.typehandle_class = mono_class_from_name (
1346 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1347 g_assert (mono_defaults.typehandle_class != 0);
1349 mono_defaults.methodhandle_class = mono_class_from_name (
1350 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1351 g_assert (mono_defaults.methodhandle_class != 0);
1353 mono_defaults.fieldhandle_class = mono_class_from_name (
1354 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1355 g_assert (mono_defaults.fieldhandle_class != 0);
1357 mono_defaults.systemtype_class = mono_class_from_name (
1358 mono_defaults.corlib, "System", "Type");
1359 g_assert (mono_defaults.systemtype_class != 0);
1361 mono_defaults.monotype_class = mono_class_from_name (
1362 mono_defaults.corlib, "System", "MonoType");
1363 g_assert (mono_defaults.monotype_class != 0);
1365 mono_defaults.exception_class = mono_class_from_name (
1366 mono_defaults.corlib, "System", "Exception");
1367 g_assert (mono_defaults.exception_class != 0);
1369 mono_defaults.threadabortexception_class = mono_class_from_name (
1370 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1371 g_assert (mono_defaults.threadabortexception_class != 0);
1373 mono_defaults.thread_class = mono_class_from_name (
1374 mono_defaults.corlib, "System.Threading", "Thread");
1375 g_assert (mono_defaults.thread_class != 0);
1377 mono_defaults.appdomain_class = mono_class_from_name (
1378 mono_defaults.corlib, "System", "AppDomain");
1379 g_assert (mono_defaults.appdomain_class != 0);
1381 mono_defaults.transparent_proxy_class = mono_class_from_name (
1382 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1383 g_assert (mono_defaults.transparent_proxy_class != 0);
1385 mono_defaults.real_proxy_class = mono_class_from_name (
1386 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1387 g_assert (mono_defaults.real_proxy_class != 0);
1389 mono_defaults.mono_method_message_class = mono_class_from_name (
1390 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1391 g_assert (mono_defaults.mono_method_message_class != 0);
1393 mono_defaults.field_info_class = mono_class_from_name (
1394 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1395 g_assert (mono_defaults.field_info_class != 0);
1397 mono_defaults.method_info_class = mono_class_from_name (
1398 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1399 g_assert (mono_defaults.method_info_class != 0);
1401 mono_defaults.stringbuilder_class = mono_class_from_name (
1402 mono_defaults.corlib, "System.Text", "StringBuilder");
1403 g_assert (mono_defaults.stringbuilder_class != 0);
1405 mono_defaults.math_class = mono_class_from_name (
1406 mono_defaults.corlib, "System", "Math");
1407 g_assert (mono_defaults.math_class != 0);
1409 mono_defaults.stack_frame_class = mono_class_from_name (
1410 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1411 g_assert (mono_defaults.stack_frame_class != 0);
1413 mono_defaults.stack_trace_class = mono_class_from_name (
1414 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1415 g_assert (mono_defaults.stack_trace_class != 0);
1417 mono_defaults.marshal_class = mono_class_from_name (
1418 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1419 g_assert (mono_defaults.marshal_class != 0);
1421 mono_defaults.iserializeable_class = mono_class_from_name (
1422 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1423 g_assert (mono_defaults.iserializeable_class != 0);
1425 mono_defaults.serializationinfo_class = mono_class_from_name (
1426 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1427 g_assert (mono_defaults.serializationinfo_class != 0);
1429 mono_defaults.streamingcontext_class = mono_class_from_name (
1430 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1431 g_assert (mono_defaults.streamingcontext_class != 0);
1433 mono_defaults.typed_reference_class = mono_class_from_name (
1434 mono_defaults.corlib, "System", "TypedReference");
1435 g_assert (mono_defaults.typed_reference_class != 0);
1437 mono_defaults.argumenthandle_class = mono_class_from_name (
1438 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1439 g_assert (mono_defaults.argumenthandle_class != 0);
1441 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1442 mono_defaults.corlib, "System", "MarshalByRefObject");
1443 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1445 mono_defaults.monitor_class = mono_class_from_name (
1446 mono_defaults.corlib, "System.Threading", "Monitor");
1447 g_assert (mono_defaults.monitor_class != 0);
1449 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1450 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1451 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1453 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1454 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1456 mono_defaults.executioncontext_class = mono_class_from_name (
1457 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1459 mono_defaults.internals_visible_class = mono_class_from_name (
1460 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1463 * mscorlib needs a little help, only now it can load its friends list (after we have
1464 * loaded the InternalsVisibleToAttribute), load it now
1466 mono_assembly_load_friends (ass);
1468 mono_defaults.safehandle_class = mono_class_from_name (
1469 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1471 mono_defaults.handleref_class = mono_class_from_name (
1472 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1474 mono_defaults.attribute_class = mono_class_from_name (
1475 mono_defaults.corlib, "System", "Attribute");
1477 mono_defaults.customattribute_data_class = mono_class_from_name (
1478 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1480 /* these are initialized lazily when COM features are used */
1481 mono_defaults.variant_class = NULL;
1482 mono_defaults.com_object_class = NULL;
1483 mono_defaults.com_interop_proxy_class = NULL;
1484 mono_defaults.iunknown_class = NULL;
1485 mono_defaults.idispatch_class = NULL;
1488 * Note that mono_defaults.generic_*_class is only non-NULL if we're
1489 * using the 2.0 corlib.
1491 mono_class_init (mono_defaults.array_class);
1492 mono_defaults.generic_nullable_class = mono_class_from_name (
1493 mono_defaults.corlib, "System", "Nullable`1");
1494 mono_defaults.generic_ilist_class = mono_class_from_name (
1495 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1497 domain->friendly_name = g_path_get_basename (filename);
1499 _mono_debug_init_corlib (domain);
1507 * Creates the initial application domain and initializes the mono_defaults
1509 * This function is guaranteed to not run any IL code.
1510 * The runtime is initialized using the default runtime version.
1512 * Returns: the initial domain.
1515 mono_init (const char *domain_name)
1517 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1521 * mono_init_from_assembly:
1523 * Creates the initial application domain and initializes the mono_defaults
1525 * This function is guaranteed to not run any IL code.
1526 * The runtime is initialized using the runtime version required by the
1527 * provided executable. The version is determined by looking at the exe
1528 * configuration file and the version PE field)
1530 * Returns: the initial domain.
1533 mono_init_from_assembly (const char *domain_name, const char *filename)
1535 return mono_init_internal (domain_name, filename, NULL);
1539 * mono_init_version:
1541 * Creates the initial application domain and initializes the mono_defaults
1543 * This function is guaranteed to not run any IL code.
1544 * The runtime is initialized using the provided rutime version.
1546 * Returns: the initial domain.
1549 mono_init_version (const char *domain_name, const char *version)
1551 return mono_init_internal (domain_name, NULL, version);
1555 * mono_init_com_types:
1557 * Initializes all types needed for COM Interop in mono_defaults structure.
1560 mono_init_com_types (void)
1562 static gboolean initialized = FALSE;
1567 /* FIXME: do I need some threading protection here */
1569 g_assert (mono_defaults.corlib);
1571 mono_defaults.variant_class = mono_class_from_name (
1572 mono_defaults.corlib, "System", "Variant");
1573 g_assert (mono_defaults.variant_class != 0);
1575 mono_defaults.com_object_class = mono_class_from_name (
1576 mono_defaults.corlib, "System", "__ComObject");
1577 g_assert (mono_defaults.com_object_class != 0);
1579 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1580 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1581 g_assert (mono_defaults.com_interop_proxy_class != 0);
1583 mono_defaults.iunknown_class = mono_class_from_name (
1584 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1585 g_assert (mono_defaults.iunknown_class != 0);
1587 mono_defaults.idispatch_class = mono_class_from_name (
1588 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1589 g_assert (mono_defaults.idispatch_class != 0);
1597 * Cleans up all metadata modules.
1603 mono_image_close (exe_image);
1605 mono_loader_cleanup ();
1606 mono_classes_cleanup ();
1607 mono_assemblies_cleanup ();
1608 mono_images_cleanup ();
1609 mono_debug_cleanup ();
1610 mono_raw_buffer_cleanup ();
1611 mono_metadata_cleanup ();
1613 TlsFree (appdomain_thread_id);
1614 DeleteCriticalSection (&appdomains_mutex);
1618 * mono_get_root_domain:
1620 * The root AppDomain is the initial domain created by the runtime when it is
1621 * initialized. Programs execute on this AppDomain, but can create new ones
1622 * later. Currently there is no unmanaged API to create new AppDomains, this
1623 * must be done from managed code.
1625 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1628 mono_get_root_domain (void)
1630 return mono_root_domain;
1636 * Returns: the current domain, to obtain the root domain use
1637 * mono_get_root_domain().
1642 return GET_APPDOMAIN ();
1646 * mono_domain_set_internal:
1647 * @domain: the new domain
1649 * Sets the current domain to @domain.
1652 mono_domain_set_internal (MonoDomain *domain)
1654 SET_APPDOMAIN (domain);
1655 SET_APPCONTEXT (domain->default_context);
1659 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1665 * Create a copy of the data to avoid calling the user callback
1666 * inside the lock because that could lead to deadlocks.
1667 * We can do this because this function is not perf. critical.
1669 mono_appdomains_lock ();
1670 size = appdomain_list_size;
1671 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1672 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1673 mono_appdomains_unlock ();
1675 for (i = 0; i < size; ++i) {
1677 func (copy [i], user_data);
1680 mono_gc_free_fixed (copy);
1684 * mono_domain_assembly_open:
1685 * @domain: the application domain
1686 * @name: file name of the assembly
1688 * fixme: maybe we should integrate this with mono_assembly_open ??
1691 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1696 mono_domain_assemblies_lock (domain);
1697 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1699 if (strcmp (name, ass->aname.name) == 0) {
1700 mono_domain_assemblies_unlock (domain);
1704 mono_domain_assemblies_unlock (domain);
1706 if (!(ass = mono_assembly_open (name, NULL)))
1713 mono_domain_lookup_shared_generic (MonoDomain *domain, MonoMethod *method)
1715 if (!domain->shared_generics_hash)
1718 return g_hash_table_lookup (domain->shared_generics_hash, method);
1722 mono_domain_register_shared_generic (MonoDomain *domain, MonoMethod *method, MonoJitInfo *jit_info)
1724 if (!domain->shared_generics_hash)
1725 domain->shared_generics_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1727 g_assert (domain->shared_generics_hash);
1729 g_hash_table_insert (domain->shared_generics_hash, method, jit_info);
1733 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
1735 MonoJitDynamicMethodInfo *di = value;
1736 mono_code_manager_destroy (di->code_mp);
1741 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
1743 g_slist_free (value);
1747 mono_domain_free (MonoDomain *domain, gboolean force)
1749 int code_size, code_alloc;
1751 if ((domain == mono_root_domain) && !force) {
1752 g_warning ("cant unload root domain");
1756 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1758 mono_debug_domain_unload (domain);
1760 mono_appdomains_lock ();
1761 appdomains_list [domain->domain_id] = NULL;
1762 mono_appdomains_unlock ();
1764 /* FIXME: free delegate_hash_table when it's used */
1765 if (domain->search_path) {
1766 g_strfreev (domain->search_path);
1767 domain->search_path = NULL;
1769 domain->create_proxy_for_type_method = NULL;
1770 domain->private_invoke_method = NULL;
1771 domain->default_context = NULL;
1772 domain->out_of_memory_ex = NULL;
1773 domain->null_reference_ex = NULL;
1774 domain->stack_overflow_ex = NULL;
1775 domain->entry_assembly = NULL;
1776 /* must do this early as it accesses fields and types */
1777 if (domain->special_static_fields) {
1778 mono_alloc_special_static_data_free (domain->special_static_fields);
1779 g_hash_table_destroy (domain->special_static_fields);
1780 domain->special_static_fields = NULL;
1782 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1783 MonoAssembly *ass = tmp->data;
1784 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);
1785 mono_assembly_close (ass);
1787 g_slist_free (domain->domain_assemblies);
1788 domain->domain_assemblies = NULL;
1790 g_free (domain->friendly_name);
1791 domain->friendly_name = NULL;
1792 mono_g_hash_table_destroy (domain->env);
1794 g_hash_table_destroy (domain->class_vtable_hash);
1795 domain->class_vtable_hash = NULL;
1796 g_hash_table_destroy (domain->proxy_vtable_hash);
1797 domain->proxy_vtable_hash = NULL;
1798 if (domain->static_data_array) {
1799 mono_gc_free_fixed (domain->static_data_array);
1800 domain->static_data_array = NULL;
1802 mono_internal_hash_table_destroy (&domain->jit_code_hash);
1803 if (domain->dynamic_code_hash) {
1804 g_hash_table_foreach (domain->dynamic_code_hash, dynamic_method_info_free, NULL);
1805 g_hash_table_destroy (domain->dynamic_code_hash);
1806 domain->dynamic_code_hash = NULL;
1808 mono_g_hash_table_destroy (domain->ldstr_table);
1809 domain->ldstr_table = NULL;
1810 jit_info_table_free (domain->jit_info_table);
1811 domain->jit_info_table = NULL;
1813 /* collect statistics */
1814 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
1815 total_domain_code_alloc += code_alloc;
1816 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
1817 max_domain_code_size = MAX (max_domain_code_size, code_size);
1819 mono_class_unregister_domain_generic_vtables (domain);
1821 #ifdef DEBUG_DOMAIN_UNLOAD
1822 mono_mempool_invalidate (domain->mp);
1823 mono_code_manager_invalidate (domain->code_mp);
1825 mono_mempool_destroy (domain->mp);
1827 mono_code_manager_destroy (domain->code_mp);
1828 domain->code_mp = NULL;
1830 if (domain->jump_target_hash) {
1831 g_hash_table_foreach (domain->jump_target_hash, delete_jump_list, NULL);
1832 g_hash_table_destroy (domain->jump_target_hash);
1833 domain->jump_target_hash = NULL;
1835 if (domain->type_hash) {
1836 mono_g_hash_table_destroy (domain->type_hash);
1837 domain->type_hash = NULL;
1839 if (domain->refobject_hash) {
1840 mono_g_hash_table_destroy (domain->refobject_hash);
1841 domain->refobject_hash = NULL;
1843 if (domain->type_init_exception_hash) {
1844 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1845 domain->type_init_exception_hash = NULL;
1847 g_hash_table_destroy (domain->class_init_trampoline_hash);
1848 domain->class_init_trampoline_hash = NULL;
1849 g_hash_table_destroy (domain->jump_trampoline_hash);
1850 domain->jump_trampoline_hash = NULL;
1851 g_hash_table_destroy (domain->finalizable_objects_hash);
1852 domain->finalizable_objects_hash = NULL;
1853 g_hash_table_destroy (domain->jit_trampoline_hash);
1854 domain->jit_trampoline_hash = NULL;
1855 g_hash_table_destroy (domain->delegate_trampoline_hash);
1856 domain->delegate_trampoline_hash = NULL;
1857 if (domain->shared_generics_hash) {
1858 g_hash_table_destroy (domain->shared_generics_hash);
1859 domain->shared_generics_hash = NULL;
1862 DeleteCriticalSection (&domain->assemblies_lock);
1863 DeleteCriticalSection (&domain->lock);
1864 domain->setup = NULL;
1866 /* FIXME: anything else required ? */
1868 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
1870 mono_gc_free_fixed (domain);
1872 if ((domain == mono_root_domain))
1873 mono_root_domain = NULL;
1877 * mono_domain_get_id:
1880 * Returns: the a domain for a specific domain id.
1883 mono_domain_get_by_id (gint32 domainid)
1885 MonoDomain * domain;
1887 mono_appdomains_lock ();
1888 if (domainid < appdomain_list_size)
1889 domain = appdomains_list [domainid];
1892 mono_appdomains_unlock ();
1898 mono_domain_get_id (MonoDomain *domain)
1900 return domain->domain_id;
1904 mono_context_set (MonoAppContext * new_context)
1906 SET_APPCONTEXT (new_context);
1910 mono_context_get (void)
1912 return GET_APPCONTEXT ();
1915 /* LOCKING: the caller holds the lock for this domain */
1917 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
1919 /* The first entry in the array is the index of the next free slot
1920 * and the total size of the array
1923 if (domain->static_data_array) {
1924 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
1925 next = GPOINTER_TO_INT (domain->static_data_array [0]);
1927 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), NULL);
1928 memcpy (new_array, domain->static_data_array, sizeof (gpointer) * size);
1930 new_array [1] = GINT_TO_POINTER (size);
1931 mono_gc_free_fixed (domain->static_data_array);
1932 domain->static_data_array = new_array;
1936 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, NULL);
1938 new_array [0] = GINT_TO_POINTER (next);
1939 new_array [1] = GINT_TO_POINTER (size);
1940 domain->static_data_array = new_array;
1942 domain->static_data_array [next++] = data;
1943 domain->static_data_array [0] = GINT_TO_POINTER (next);
1947 mono_get_corlib (void)
1949 return mono_defaults.corlib;
1953 mono_get_object_class (void)
1955 return mono_defaults.object_class;
1959 mono_get_byte_class (void)
1961 return mono_defaults.byte_class;
1965 mono_get_void_class (void)
1967 return mono_defaults.void_class;
1971 mono_get_boolean_class (void)
1973 return mono_defaults.boolean_class;
1977 mono_get_sbyte_class (void)
1979 return mono_defaults.sbyte_class;
1983 mono_get_int16_class (void)
1985 return mono_defaults.int16_class;
1989 mono_get_uint16_class (void)
1991 return mono_defaults.uint16_class;
1995 mono_get_int32_class (void)
1997 return mono_defaults.int32_class;
2001 mono_get_uint32_class (void)
2003 return mono_defaults.uint32_class;
2007 mono_get_intptr_class (void)
2009 return mono_defaults.int_class;
2013 mono_get_uintptr_class (void)
2015 return mono_defaults.uint_class;
2019 mono_get_int64_class (void)
2021 return mono_defaults.int64_class;
2025 mono_get_uint64_class (void)
2027 return mono_defaults.uint64_class;
2031 mono_get_single_class (void)
2033 return mono_defaults.single_class;
2037 mono_get_double_class (void)
2039 return mono_defaults.double_class;
2043 mono_get_char_class (void)
2045 return mono_defaults.char_class;
2049 mono_get_string_class (void)
2051 return mono_defaults.string_class;
2055 mono_get_enum_class (void)
2057 return mono_defaults.enum_class;
2061 mono_get_array_class (void)
2063 return mono_defaults.array_class;
2067 mono_get_thread_class (void)
2069 return mono_defaults.thread_class;
2073 mono_get_exception_class (void)
2075 return mono_defaults.exception_class;
2079 static char* get_attribute_value (const gchar **attribute_names,
2080 const gchar **attribute_values,
2081 const char *att_name)
2084 for (n=0; attribute_names[n] != NULL; n++) {
2085 if (strcmp (attribute_names[n], att_name) == 0)
2086 return g_strdup (attribute_values[n]);
2091 static void start_element (GMarkupParseContext *context,
2092 const gchar *element_name,
2093 const gchar **attribute_names,
2094 const gchar **attribute_values,
2098 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2100 if (strcmp (element_name, "configuration") == 0) {
2101 app_config->configuration_count++;
2104 if (strcmp (element_name, "startup") == 0) {
2105 app_config->startup_count++;
2109 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2112 if (strcmp (element_name, "requiredRuntime") == 0) {
2113 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2114 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2115 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2116 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2120 static void end_element (GMarkupParseContext *context,
2121 const gchar *element_name,
2125 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2127 if (strcmp (element_name, "configuration") == 0) {
2128 app_config->configuration_count--;
2129 } else if (strcmp (element_name, "startup") == 0) {
2130 app_config->startup_count--;
2134 static const GMarkupParser
2143 static AppConfigInfo *
2144 app_config_parse (const char *exe_filename)
2146 AppConfigInfo *app_config;
2147 GMarkupParseContext *context;
2151 const char *bundled_config;
2152 char *config_filename;
2154 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2156 if (bundled_config) {
2157 text = g_strdup (bundled_config);
2158 len = strlen (text);
2160 config_filename = g_strconcat (exe_filename, ".config", NULL);
2162 if (stat (config_filename, &buf) != 0) {
2163 g_free (config_filename);
2167 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2168 g_free (config_filename);
2171 g_free (config_filename);
2174 app_config = g_new0 (AppConfigInfo, 1);
2176 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2177 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2178 g_markup_parse_context_end_parse (context, NULL);
2180 g_markup_parse_context_free (context);
2186 app_config_free (AppConfigInfo* app_config)
2189 GSList *list = app_config->supported_runtimes;
2190 while (list != NULL) {
2191 rt = (char*)list->data;
2193 list = g_slist_next (list);
2195 g_slist_free (app_config->supported_runtimes);
2196 g_free (app_config->required_runtime);
2197 g_free (app_config);
2201 static const MonoRuntimeInfo*
2202 get_runtime_by_version (const char *version)
2205 int max = G_N_ELEMENTS (supported_runtimes);
2207 for (n=0; n<max; n++) {
2208 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2209 return &supported_runtimes[n];
2215 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2217 AppConfigInfo* app_config;
2219 const MonoRuntimeInfo* runtime = NULL;
2220 MonoImage *image = NULL;
2222 app_config = app_config_parse (exe_file);
2224 if (app_config != NULL) {
2225 /* Check supportedRuntime elements, if none is supported, fail.
2226 * If there are no such elements, look for a requiredRuntime element.
2228 if (app_config->supported_runtimes != NULL) {
2230 GSList *list = app_config->supported_runtimes;
2231 while (list != NULL) {
2232 version = (char*) list->data;
2233 runtime = get_runtime_by_version (version);
2234 if (runtime != NULL)
2235 runtimes [n++] = runtime;
2236 list = g_slist_next (list);
2238 runtimes [n] = NULL;
2239 app_config_free (app_config);
2243 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2244 if (app_config->required_runtime != NULL) {
2245 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2246 runtimes [1] = NULL;
2247 app_config_free (app_config);
2250 app_config_free (app_config);
2253 /* Look for a runtime with the exact version */
2254 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2257 image = mono_image_open (exe_file, NULL);
2259 if (image == NULL) {
2260 /* The image is wrong or the file was not found. In this case return
2261 * a default runtime and leave to the initialization method the work of
2262 * reporting the error.
2264 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2265 runtimes [1] = NULL;
2271 runtimes [0] = get_runtime_by_version (image->version);
2272 runtimes [1] = NULL;
2277 * mono_get_runtime_info:
2279 * Returns: the version of the current runtime instance.
2281 const MonoRuntimeInfo*
2282 mono_get_runtime_info (void)
2284 return current_runtime;
2288 mono_debugger_check_runtime_version (const char *filename)
2290 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2291 const MonoRuntimeInfo *rinfo;
2294 get_runtimes_from_exe (filename, &image, runtimes);
2295 rinfo = runtimes [0];
2298 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2300 if (rinfo != current_runtime)
2301 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2302 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2303 filename, rinfo->runtime_version);