2 * domain.c: MonoDomain functions
5 * Dietmar Maurer (dietmar@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com)
18 #include <mono/metadata/gc-internal.h>
20 #include <mono/utils/mono-compiler.h>
21 #include <mono/utils/mono-logger-internal.h>
22 #include <mono/utils/mono-membar.h>
23 #include <mono/utils/mono-counters.h>
24 #include <mono/utils/hazard-pointer.h>
25 #include <mono/utils/mono-tls.h>
26 #include <mono/metadata/object.h>
27 #include <mono/metadata/object-internals.h>
28 #include <mono/metadata/domain-internals.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/assembly.h>
31 #include <mono/metadata/exception.h>
32 #include <mono/metadata/metadata-internals.h>
33 #include <mono/metadata/gc-internal.h>
34 #include <mono/metadata/appdomain.h>
35 #include <mono/metadata/mono-debug-debugger.h>
36 #include <mono/metadata/mono-config.h>
37 #include <mono/metadata/threads-types.h>
38 #include <metadata/threads.h>
39 #include <metadata/profiler-private.h>
40 #include <mono/metadata/coree.h>
42 /* #define DEBUG_DOMAIN_UNLOAD */
44 /* we need to use both the Tls* functions and __thread because
45 * some archs may generate faster jit code with one meachanism
46 * or the other (we used to do it because tls slots were GC-tracked,
47 * but we can't depend on this).
49 static MonoNativeTlsKey appdomain_thread_id;
51 #ifdef MONO_HAVE_FAST_TLS
53 MONO_FAST_TLS_DECLARE(tls_appdomain);
55 #define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain))
57 #define SET_APPDOMAIN(x) do { \
58 MONO_FAST_TLS_SET (tls_appdomain,x); \
59 mono_native_tls_set_value (appdomain_thread_id, x); \
60 mono_gc_set_current_thread_appdomain (x); \
63 #else /* !MONO_HAVE_FAST_TLS */
65 #define GET_APPDOMAIN() ((MonoDomain *)mono_native_tls_get_value (appdomain_thread_id))
66 #define SET_APPDOMAIN(x) do { \
67 mono_native_tls_set_value (appdomain_thread_id, x); \
68 mono_gc_set_current_thread_appdomain (x); \
73 #define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext)
74 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x))
76 static guint16 appdomain_list_size = 0;
77 static guint16 appdomain_next = 0;
78 static MonoDomain **appdomains_list = NULL;
79 static MonoImage *exe_image;
81 gboolean mono_dont_free_domains;
83 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
84 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
85 static CRITICAL_SECTION appdomains_mutex;
87 static MonoDomain *mono_root_domain = NULL;
90 static int max_domain_code_size = 0;
91 static int max_domain_code_alloc = 0;
92 static int total_domain_code_alloc = 0;
94 /* AppConfigInfo: Information about runtime versions supported by an
98 GSList *supported_runtimes;
99 char *required_runtime;
100 int configuration_count;
105 * AotModuleInfo: Contains information about AOT modules.
112 static const MonoRuntimeInfo *current_runtime = NULL;
114 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
117 * Contains information about AOT loaded code.
119 static MonoAotModuleInfoTable *aot_modules = NULL;
121 /* This is the list of runtime versions supported by this JIT.
123 static const MonoRuntimeInfo supported_runtimes[] = {
124 {"v2.0.50215","2.0", { {2,0,0,0}, { 8,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
125 {"v2.0.50727","2.0", { {2,0,0,0}, { 8,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
126 {"v4.0.30319","4.5", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
127 {"v4.0.30128","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
128 {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
129 {"moonlight", "2.1", { {2,0,5,0}, { 9,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
133 /* The stable runtime version */
134 #define DEFAULT_RUNTIME_VERSION "v2.0.50727"
136 /* Callbacks installed by the JIT */
137 static MonoCreateDomainFunc create_domain_hook;
138 static MonoFreeDomainFunc free_domain_hook;
140 /* This is intentionally not in the header file, so people don't misuse it. */
141 extern void _mono_debug_init_corlib (MonoDomain *domain);
144 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
146 static const MonoRuntimeInfo*
147 get_runtime_by_version (const char *version);
150 mono_jit_info_find_aot_module (guint8* addr);
153 mono_domain_get_tls_key (void)
155 return appdomain_thread_id;
159 mono_domain_get_tls_offset (void)
162 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
163 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
168 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
169 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
170 #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)
172 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
173 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
175 #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
176 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
178 #define JIT_INFO_TABLE_HAZARD_INDEX 0
179 #define JIT_INFO_HAZARD_INDEX 1
182 jit_info_table_num_elements (MonoJitInfoTable *table)
185 int num_elements = 0;
187 for (i = 0; i < table->num_chunks; ++i) {
188 MonoJitInfoTableChunk *chunk = table->chunks [i];
189 int chunk_num_elements = chunk->num_elements;
192 for (j = 0; j < chunk_num_elements; ++j) {
193 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
201 static MonoJitInfoTableChunk*
202 jit_info_table_new_chunk (void)
204 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
210 static MonoJitInfoTable *
211 jit_info_table_new (MonoDomain *domain)
213 MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
215 table->domain = domain;
216 table->num_chunks = 1;
217 table->chunks [0] = jit_info_table_new_chunk ();
223 jit_info_table_free (MonoJitInfoTable *table)
226 int num_chunks = table->num_chunks;
227 MonoDomain *domain = table->domain;
229 mono_domain_lock (domain);
231 table->domain->num_jit_info_tables--;
232 if (table->domain->num_jit_info_tables <= 1) {
235 for (list = table->domain->jit_info_free_queue; list; list = list->next)
238 g_slist_free (table->domain->jit_info_free_queue);
239 table->domain->jit_info_free_queue = NULL;
242 /* At this point we assume that there are no other threads
243 still accessing the table, so we don't have to worry about
244 hazardous pointers. */
246 for (i = 0; i < num_chunks; ++i) {
247 MonoJitInfoTableChunk *chunk = table->chunks [i];
251 if (--chunk->refcount > 0)
254 num_elements = chunk->num_elements;
255 for (j = 0; j < num_elements; ++j) {
256 MonoJitInfo *ji = chunk->data [j];
258 if (IS_JIT_INFO_TOMBSTONE (ji))
265 mono_domain_unlock (domain);
270 /* The jit_info_table is sorted in ascending order by the end
271 * addresses of the compiled methods. The reason why we have to do
272 * this is that once we introduce tombstones, it becomes possible for
273 * code ranges to overlap, and if we sort by code start and insert at
274 * the back of the table, we cannot guarantee that we won't overlook
277 * There are actually two possible ways to do the sorting and
278 * inserting which work with our lock-free mechanism:
280 * 1. Sort by start address and insert at the front. When looking for
281 * an entry, find the last one with a start address lower than the one
282 * you're looking for, then work your way to the front of the table.
284 * 2. Sort by end address and insert at the back. When looking for an
285 * entry, find the first one with an end address higher than the one
286 * you're looking for, then work your way to the end of the table.
288 * We chose the latter out of convenience.
291 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
293 int left = 0, right = table->num_chunks;
295 g_assert (left < right);
298 int pos = (left + right) / 2;
299 MonoJitInfoTableChunk *chunk = table->chunks [pos];
301 if (addr < chunk->last_code_end)
305 } while (left < right);
306 g_assert (left == right);
308 if (left >= table->num_chunks)
309 return table->num_chunks - 1;
314 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
316 int left = 0, right = chunk->num_elements;
318 while (left < right) {
319 int pos = (left + right) / 2;
320 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
321 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
328 g_assert (left == right);
334 mono_jit_info_table_find (MonoDomain *domain, char *addr)
336 MonoJitInfoTable *table;
339 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
342 ++mono_stats.jit_info_table_lookup_count;
344 /* First we have to get the domain's jit_info_table. This is
345 complicated by the fact that a writer might substitute a
346 new table and free the old one. What the writer guarantees
347 us is that it looks at the hazard pointers after it has
348 changed the jit_info_table pointer. So, if we guard the
349 table by a hazard pointer and make sure that the pointer is
350 still there after we've made it hazardous, we don't have to
351 worry about the writer freeing the table. */
352 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
354 chunk_pos = jit_info_table_index (table, (gint8*)addr);
355 g_assert (chunk_pos < table->num_chunks);
357 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
359 /* We now have a position that's very close to that of the
360 first element whose end address is higher than the one
361 we're looking for. If we don't have the exact position,
362 then we have a position below that one, so we'll just
363 search upward until we find our element. */
365 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
367 while (pos < chunk->num_elements) {
368 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
372 if (IS_JIT_INFO_TOMBSTONE (ji)) {
373 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
376 if ((gint8*)addr >= (gint8*)ji->code_start
377 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
378 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
379 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
383 /* If we find a non-tombstone element which is already
384 beyond what we're looking for, we have to end the
386 if ((gint8*)addr < (gint8*)ji->code_start)
392 } while (chunk_pos < table->num_chunks);
398 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
399 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
403 /* Maybe its an AOT module */
404 image = mono_jit_info_find_aot_module ((guint8*)addr);
406 ji = jit_info_find_in_aot_func (domain, image, addr);
411 static G_GNUC_UNUSED void
412 jit_info_table_check (MonoJitInfoTable *table)
416 for (i = 0; i < table->num_chunks; ++i) {
417 MonoJitInfoTableChunk *chunk = table->chunks [i];
420 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
421 if (chunk->refcount > 10)
422 printf("warning: chunk refcount is %d\n", chunk->refcount);
423 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
425 for (j = 0; j < chunk->num_elements; ++j) {
426 MonoJitInfo *this = chunk->data [j];
429 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
431 if (j < chunk->num_elements - 1)
432 next = chunk->data [j + 1];
433 else if (i < table->num_chunks - 1) {
436 for (k = i + 1; k < table->num_chunks; ++k)
437 if (table->chunks [k]->num_elements > 0)
440 if (k >= table->num_chunks)
443 g_assert (table->chunks [k]->num_elements > 0);
444 next = table->chunks [k]->data [0];
448 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
453 static MonoJitInfoTable*
454 jit_info_table_realloc (MonoJitInfoTable *old)
457 int num_elements = jit_info_table_num_elements (old);
460 int new_chunk, new_element;
461 MonoJitInfoTable *new;
463 /* number of needed places for elements needed */
464 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
465 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
466 if (num_chunks == 0) {
467 g_assert (num_elements == 0);
468 return jit_info_table_new (old->domain);
470 g_assert (num_chunks > 0);
472 new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
473 new->domain = old->domain;
474 new->num_chunks = num_chunks;
476 for (i = 0; i < num_chunks; ++i)
477 new->chunks [i] = jit_info_table_new_chunk ();
481 for (i = 0; i < old->num_chunks; ++i) {
482 MonoJitInfoTableChunk *chunk = old->chunks [i];
483 int chunk_num_elements = chunk->num_elements;
486 for (j = 0; j < chunk_num_elements; ++j) {
487 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
488 g_assert (new_chunk < num_chunks);
489 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
490 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
491 new->chunks [new_chunk]->num_elements = new_element;
499 if (new_chunk < num_chunks) {
500 g_assert (new_chunk == num_chunks - 1);
501 new->chunks [new_chunk]->num_elements = new_element;
502 g_assert (new->chunks [new_chunk]->num_elements > 0);
505 for (i = 0; i < num_chunks; ++i) {
506 MonoJitInfoTableChunk *chunk = new->chunks [i];
507 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
509 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
516 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
518 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
519 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
521 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
523 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
524 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
526 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
527 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
529 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
530 + new1->data [new1->num_elements - 1]->code_size;
531 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
532 + new2->data [new2->num_elements - 1]->code_size;
538 static MonoJitInfoTable*
539 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
541 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
542 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
545 new_table->domain = table->domain;
546 new_table->num_chunks = table->num_chunks + 1;
549 for (i = 0; i < table->num_chunks; ++i) {
550 if (table->chunks [i] == chunk) {
551 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
554 new_table->chunks [j] = table->chunks [i];
555 ++new_table->chunks [j]->refcount;
560 g_assert (j == new_table->num_chunks);
565 static MonoJitInfoTableChunk*
566 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
568 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
572 for (i = 0; i < old->num_elements; ++i) {
573 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
574 new->data [j++] = old->data [i];
577 new->num_elements = j;
578 if (new->num_elements > 0)
579 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
581 new->last_code_end = old->last_code_end;
586 static MonoJitInfoTable*
587 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
589 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
590 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
593 new_table->domain = table->domain;
594 new_table->num_chunks = table->num_chunks;
597 for (i = 0; i < table->num_chunks; ++i) {
598 if (table->chunks [i] == chunk)
599 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
601 new_table->chunks [j] = table->chunks [i];
602 ++new_table->chunks [j]->refcount;
607 g_assert (j == new_table->num_chunks);
612 /* As we add an element to the table the case can arise that the chunk
613 * to which we need to add is already full. In that case we have to
614 * allocate a new table and do something about that chunk. We have
615 * several strategies:
617 * If the number of elements in the table is below the low watermark
618 * or above the high watermark, we reallocate the whole table.
619 * Otherwise we only concern ourselves with the overflowing chunk:
621 * If there are no tombstones in the chunk then we split the chunk in
622 * two, each half full.
624 * If the chunk does contain tombstones, we just make a new copy of
625 * the chunk without the tombstones, which will have room for at least
626 * the one element we have to add.
628 static MonoJitInfoTable*
629 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
631 int num_elements = jit_info_table_num_elements (table);
634 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
635 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
636 //printf ("reallocing table\n");
637 return jit_info_table_realloc (table);
640 /* count the number of non-tombstone elements in the chunk */
642 for (i = 0; i < chunk->num_elements; ++i) {
643 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
647 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
648 //printf ("splitting chunk\n");
649 return jit_info_table_copy_and_split_chunk (table, chunk);
652 //printf ("purifying chunk\n");
653 return jit_info_table_copy_and_purify_chunk (table, chunk);
656 /* We add elements to the table by first making space for them by
657 * shifting the elements at the back to the right, one at a time.
658 * This results in duplicate entries during the process, but during
659 * all the time the table is in a sorted state. Also, when an element
660 * is replaced by another one, the element that replaces it has an end
661 * address that is equal to or lower than that of the replaced
662 * element. That property is necessary to guarantee that when
663 * searching for an element we end up at a position not higher than
664 * the one we're looking for (i.e. we either find the element directly
665 * or we end up to the left of it).
668 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
670 MonoJitInfoTable *table;
672 MonoJitInfoTableChunk *chunk;
676 g_assert (ji->method != NULL);
678 mono_domain_lock (domain);
680 ++mono_stats.jit_info_table_insert_count;
682 table = domain->jit_info_table;
685 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
686 g_assert (chunk_pos < table->num_chunks);
687 chunk = table->chunks [chunk_pos];
689 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
690 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
692 /* Debugging code, should be removed. */
693 //jit_info_table_check (new_table);
695 domain->jit_info_table = new_table;
696 mono_memory_barrier ();
697 domain->num_jit_info_tables++;
698 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free, TRUE, FALSE);
704 /* Debugging code, should be removed. */
705 //jit_info_table_check (table);
707 num_elements = chunk->num_elements;
709 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
711 /* First we need to size up the chunk by one, by copying the
712 last item, or inserting the first one, if the table is
714 if (num_elements > 0)
715 chunk->data [num_elements] = chunk->data [num_elements - 1];
717 chunk->data [0] = ji;
718 mono_memory_write_barrier ();
719 chunk->num_elements = ++num_elements;
721 /* Shift the elements up one by one. */
722 for (i = num_elements - 2; i >= pos; --i) {
723 mono_memory_write_barrier ();
724 chunk->data [i + 1] = chunk->data [i];
727 /* Now we have room and can insert the new item. */
728 mono_memory_write_barrier ();
729 chunk->data [pos] = ji;
731 /* Set the high code end address chunk entry. */
732 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
733 + chunk->data [chunk->num_elements - 1]->code_size;
735 /* Debugging code, should be removed. */
736 //jit_info_table_check (table);
738 mono_domain_unlock (domain);
742 mono_jit_info_make_tombstone (MonoJitInfo *ji)
744 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
746 tombstone->code_start = ji->code_start;
747 tombstone->code_size = ji->code_size;
748 tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
754 * LOCKING: domain lock
757 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
759 if (domain->num_jit_info_tables <= 1) {
760 /* Can it actually happen that we only have one table
761 but ji is still hazardous? */
762 mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
764 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
769 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
771 MonoJitInfoTable *table;
772 MonoJitInfoTableChunk *chunk;
773 gpointer start = ji->code_start;
776 mono_domain_lock (domain);
777 table = domain->jit_info_table;
779 ++mono_stats.jit_info_table_remove_count;
781 chunk_pos = jit_info_table_index (table, start);
782 g_assert (chunk_pos < table->num_chunks);
784 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
787 chunk = table->chunks [chunk_pos];
789 while (pos < chunk->num_elements) {
790 if (chunk->data [pos] == ji)
793 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
794 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
795 <= (guint8*)ji->code_start + ji->code_size);
802 } while (chunk_pos < table->num_chunks);
805 g_assert (chunk->data [pos] == ji);
807 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
809 /* Debugging code, should be removed. */
810 //jit_info_table_check (table);
812 mono_jit_info_free_or_queue (domain, ji);
814 mono_domain_unlock (domain);
817 static MonoAotModuleInfoTable*
818 mono_aot_module_info_table_new (void)
820 return g_array_new (FALSE, FALSE, sizeof (gpointer));
824 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
826 int left = 0, right = table->len;
828 while (left < right) {
829 int pos = (left + right) / 2;
830 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
831 char *start = ainfo->start;
832 char *end = ainfo->end;
836 else if (addr >= end)
846 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
848 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
851 ainfo->image = image;
852 ainfo->start = start;
855 mono_appdomains_lock ();
858 aot_modules = mono_aot_module_info_table_new ();
860 pos = aot_info_table_index (aot_modules, start);
862 g_array_insert_val (aot_modules, pos, ainfo);
864 mono_appdomains_unlock ();
868 mono_jit_info_find_aot_module (guint8* addr)
870 guint left = 0, right;
875 mono_appdomains_lock ();
877 right = aot_modules->len;
878 while (left < right) {
879 guint pos = (left + right) / 2;
880 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
882 if (addr < (guint8*)ai->start)
884 else if (addr >= (guint8*)ai->end)
887 mono_appdomains_unlock ();
892 mono_appdomains_unlock ();
898 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
900 jit_info_find_in_aot_func = func;
904 mono_jit_info_get_code_start (MonoJitInfo* ji)
906 return ji->code_start;
910 mono_jit_info_get_code_size (MonoJitInfo* ji)
912 return ji->code_size;
916 mono_jit_info_get_method (MonoJitInfo* ji)
922 jit_info_key_extract (gpointer value)
924 MonoJitInfo *info = (MonoJitInfo*)value;
930 jit_info_next_value (gpointer value)
932 MonoJitInfo *info = (MonoJitInfo*)value;
934 return (gpointer*)&info->next_jit_code_hash;
938 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
940 mono_internal_hash_table_init (jit_code_hash,
941 mono_aligned_addr_hash,
942 jit_info_key_extract,
943 jit_info_next_value);
947 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
949 if (ji->has_generic_jit_info)
950 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
955 #ifdef USE_JUMP_TABLES
957 #define DEFAULT_JUMPTABLE_CHUNK_ELEMENTS 128
959 typedef struct MonoJumpTableChunk {
962 struct MonoJumpTableChunk *previous;
963 /* gpointer entries[total]; */
964 } MonoJumpTableChunk;
966 static MonoJumpTableChunk* g_jumptable = NULL;
967 #define mono_jumptable_lock() EnterCriticalSection (&jumptable_mutex)
968 #define mono_jumptable_unlock() LeaveCriticalSection (&jumptable_mutex)
969 static CRITICAL_SECTION jumptable_mutex;
971 static MonoJumpTableChunk*
972 mono_create_jumptable_chunk (guint32 max_entries)
974 guint32 size = sizeof (MonoJumpTableChunk) + max_entries * sizeof(gpointer);
975 MonoJumpTableChunk *chunk = (MonoJumpTableChunk*) g_new0 (guchar, size);
976 chunk->total = max_entries;
981 mono_jumptable_init (void)
983 if (g_jumptable == NULL) {
984 InitializeCriticalSection (&jumptable_mutex);
985 g_jumptable = mono_create_jumptable_chunk (DEFAULT_JUMPTABLE_CHUNK_ELEMENTS);
990 mono_jumptable_add_entry (void)
992 return mono_jumptable_add_entries (1);
996 mono_jumptable_add_entries (guint32 entries)
1001 mono_jumptable_init ();
1002 mono_jumptable_lock ();
1003 index = g_jumptable->active;
1004 if (index + entries >= g_jumptable->total) {
1006 * Grow jumptable, by adding one more chunk.
1007 * We cannot realloc jumptable, as there could be pointers
1008 * to existing jump table entries in the code, so instead
1009 * we just add one more chunk.
1011 guint32 max_entries = entries;
1012 MonoJumpTableChunk *new_chunk;
1014 if (max_entries < DEFAULT_JUMPTABLE_CHUNK_ELEMENTS)
1015 max_entries = DEFAULT_JUMPTABLE_CHUNK_ELEMENTS;
1016 new_chunk = mono_create_jumptable_chunk (max_entries);
1017 /* Link old jumptable, so that we could free it up later. */
1018 new_chunk->previous = g_jumptable;
1019 g_jumptable = new_chunk;
1022 g_jumptable->active = index + entries;
1023 result = (gpointer*)((guchar*)g_jumptable + sizeof(MonoJumpTableChunk)) + index;
1024 mono_jumptable_unlock();
1030 mono_jumptable_cleanup (void)
1033 MonoJumpTableChunk *current = g_jumptable, *prev;
1034 while (current != NULL) {
1035 prev = current->previous;
1040 DeleteCriticalSection (&jumptable_mutex);
1046 * mono_jit_info_get_generic_sharing_context:
1049 * Returns the jit info's generic sharing context, or NULL if it
1052 MonoGenericSharingContext*
1053 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
1055 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
1058 return gi->generic_sharing_context;
1064 * mono_jit_info_set_generic_sharing_context:
1066 * @gsctx: a generic sharing context
1068 * Sets the jit info's generic sharing context. The jit info must
1069 * have memory allocated for the context.
1072 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
1074 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
1078 gi->generic_sharing_context = gsctx;
1081 MonoTryBlockHoleTableJitInfo*
1082 mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
1084 if (ji->has_try_block_holes) {
1085 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1086 if (ji->has_generic_jit_info)
1087 ptr += sizeof (MonoGenericJitInfo);
1088 return (MonoTryBlockHoleTableJitInfo*)ptr;
1095 mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
1097 if (ji->has_arch_eh_info) {
1098 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1099 if (ji->has_generic_jit_info)
1100 ptr += sizeof (MonoGenericJitInfo);
1101 if (ji->has_try_block_holes)
1102 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
1103 return (MonoArchEHJitInfo*)ptr;
1110 mono_jit_info_get_cas_info (MonoJitInfo *ji)
1112 if (ji->has_cas_info) {
1113 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1114 if (ji->has_generic_jit_info)
1115 ptr += sizeof (MonoGenericJitInfo);
1116 if (ji->has_try_block_holes)
1117 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
1118 if (ji->has_arch_eh_info)
1119 ptr += sizeof (MonoArchEHJitInfo);
1120 return (MonoMethodCasInfo*)ptr;
1127 mono_install_create_domain_hook (MonoCreateDomainFunc func)
1129 create_domain_hook = func;
1133 mono_install_free_domain_hook (MonoFreeDomainFunc func)
1135 free_domain_hook = func;
1139 * mono_string_equal:
1140 * @s1: First string to compare
1141 * @s2: Second string to compare
1143 * Returns FALSE if the strings differ.
1146 mono_string_equal (MonoString *s1, MonoString *s2)
1148 int l1 = mono_string_length (s1);
1149 int l2 = mono_string_length (s2);
1156 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
1161 * @s: the string to hash
1163 * Returns the hash for the string.
1166 mono_string_hash (MonoString *s)
1168 const guint16 *p = mono_string_chars (s);
1169 int i, len = mono_string_length (s);
1172 for (i = 0; i < len; i++) {
1173 h = (h << 5) - h + *p;
1181 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1183 int len = GPOINTER_TO_INT (s1 [0]);
1184 if (len != GPOINTER_TO_INT (s2 [0]))
1187 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1191 mono_ptrarray_hash (gpointer *s)
1194 int len = GPOINTER_TO_INT (s [0]);
1197 for (i = 1; i < len; i++)
1198 hash += GPOINTER_TO_UINT (s [i]);
1204 * Allocate an id for domain and set domain->domain_id.
1205 * LOCKING: must be called while holding appdomains_mutex.
1206 * We try to assign low numbers to the domain, so it can be used
1207 * as an index in data tables to lookup domain-specific info
1208 * with minimal memory overhead. We also try not to reuse the
1209 * same id too quickly (to help debugging).
1212 domain_id_alloc (MonoDomain *domain)
1215 if (!appdomains_list) {
1216 appdomain_list_size = 2;
1217 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1219 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1220 if (!appdomains_list [i]) {
1226 for (i = 0; i < appdomain_next; ++i) {
1227 if (!appdomains_list [i]) {
1234 MonoDomain **new_list;
1235 int new_size = appdomain_list_size * 2;
1236 if (new_size >= (1 << 16))
1237 g_assert_not_reached ();
1238 id = appdomain_list_size;
1239 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1240 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1241 mono_gc_free_fixed (appdomains_list);
1242 appdomains_list = new_list;
1243 appdomain_list_size = new_size;
1245 domain->domain_id = id;
1246 appdomains_list [id] = domain;
1248 if (appdomain_next > appdomain_list_size)
1253 static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1254 static gpointer domain_gc_desc = NULL;
1255 static guint32 domain_shadow_serial = 0L;
1258 mono_domain_create (void)
1261 guint32 shadow_serial;
1263 mono_appdomains_lock ();
1264 shadow_serial = domain_shadow_serial++;
1266 if (!domain_gc_desc) {
1267 unsigned int i, bit = 0;
1268 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1269 bit = i / sizeof (gpointer);
1270 domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32);
1272 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1274 mono_appdomains_unlock ();
1276 #ifdef HAVE_BOEHM_GC
1278 * Boehm doesn't like roots inside GC allocated objects, and alloc_fixed returns
1279 * a GC_MALLOC-ed object, contrary to the api docs. This causes random crashes when
1280 * running the corlib test suite.
1281 * To solve this, we pass a NULL descriptor, and don't register roots.
1283 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL);
1285 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1286 mono_gc_register_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED), G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_LAST_GC_TRACKED) - G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED), NULL);
1288 domain->shadow_serial = shadow_serial;
1289 domain->domain = NULL;
1290 domain->setup = NULL;
1291 domain->friendly_name = NULL;
1292 domain->search_path = NULL;
1294 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1296 domain->mp = mono_mempool_new ();
1297 domain->code_mp = mono_code_manager_new ();
1298 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1299 domain->domain_assemblies = NULL;
1300 domain->assembly_bindings = NULL;
1301 domain->assembly_bindings_parsed = FALSE;
1302 domain->class_vtable_array = g_ptr_array_new ();
1303 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1304 domain->static_data_array = NULL;
1305 mono_jit_code_hash_init (&domain->jit_code_hash);
1306 domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1307 domain->num_jit_info_tables = 1;
1308 domain->jit_info_table = jit_info_table_new (domain);
1309 domain->jit_info_free_queue = NULL;
1310 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1311 domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1313 InitializeCriticalSection (&domain->lock);
1314 InitializeCriticalSection (&domain->assemblies_lock);
1315 InitializeCriticalSection (&domain->jit_code_hash_lock);
1316 InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
1318 domain->method_rgctx_hash = NULL;
1320 mono_appdomains_lock ();
1321 domain_id_alloc (domain);
1322 mono_appdomains_unlock ();
1324 #ifndef DISABLE_PERFCOUNTERS
1325 mono_perfcounters->loader_appdomains++;
1326 mono_perfcounters->loader_total_appdomains++;
1329 mono_debug_domain_create (domain);
1331 if (create_domain_hook)
1332 create_domain_hook (domain);
1334 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1340 * mono_init_internal:
1342 * Creates the initial application domain and initializes the mono_defaults
1344 * This function is guaranteed to not run any IL code.
1345 * If exe_filename is not NULL, the method will determine the required runtime
1346 * from the exe configuration file or the version PE field.
1347 * If runtime_version is not NULL, that runtime version will be used.
1348 * Either exe_filename or runtime_version must be provided.
1350 * Returns: the initial domain.
1353 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1355 static MonoDomain *domain = NULL;
1356 MonoAssembly *ass = NULL;
1357 MonoImageOpenStatus status = MONO_IMAGE_OK;
1358 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1362 g_assert_not_reached ();
1365 /* Avoid system error message boxes. */
1366 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1373 #ifndef DISABLE_PERFCOUNTERS
1374 mono_perfcounters_init ();
1377 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1378 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1379 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1381 mono_gc_base_init ();
1383 MONO_FAST_TLS_INIT (tls_appdomain);
1384 mono_native_tls_alloc (&appdomain_thread_id, NULL);
1386 InitializeCriticalSection (&appdomains_mutex);
1388 mono_metadata_init ();
1389 mono_images_init ();
1390 mono_assemblies_init ();
1391 mono_classes_init ();
1392 mono_loader_init ();
1393 mono_reflection_init ();
1395 /* FIXME: When should we release this memory? */
1396 MONO_GC_REGISTER_ROOT_FIXED (appdomains_list);
1398 domain = mono_domain_create ();
1399 mono_root_domain = domain;
1401 SET_APPDOMAIN (domain);
1403 /* Get a list of runtimes supported by the exe */
1404 if (exe_filename != NULL) {
1406 * This function will load the exe file as a MonoImage. We need to close it, but
1407 * that would mean it would be reloaded later. So instead, we save it to
1408 * exe_image, and close it during shutdown.
1410 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1413 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1415 exe_image = mono_image_open (exe_filename, NULL);
1417 mono_fixup_exe_image (exe_image);
1419 } else if (runtime_version != NULL) {
1420 runtimes [0] = get_runtime_by_version (runtime_version);
1421 runtimes [1] = NULL;
1424 if (runtimes [0] == NULL) {
1425 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1426 runtimes [0] = default_runtime;
1427 runtimes [1] = NULL;
1428 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1429 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1432 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1433 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1434 current_runtime = runtimes [n];
1435 ass = mono_assembly_load_corlib (current_runtime, &status);
1436 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1441 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1443 case MONO_IMAGE_ERROR_ERRNO: {
1444 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1445 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1446 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1447 g_free (corlib_file);
1450 case MONO_IMAGE_IMAGE_INVALID:
1451 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1452 mono_assembly_getrootdir ());
1454 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1455 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1456 mono_assembly_getrootdir ());
1459 /* to suppress compiler warning */
1465 mono_defaults.corlib = mono_assembly_get_image (ass);
1467 mono_defaults.object_class = mono_class_from_name (
1468 mono_defaults.corlib, "System", "Object");
1469 g_assert (mono_defaults.object_class != 0);
1471 mono_defaults.void_class = mono_class_from_name (
1472 mono_defaults.corlib, "System", "Void");
1473 g_assert (mono_defaults.void_class != 0);
1475 mono_defaults.boolean_class = mono_class_from_name (
1476 mono_defaults.corlib, "System", "Boolean");
1477 g_assert (mono_defaults.boolean_class != 0);
1479 mono_defaults.byte_class = mono_class_from_name (
1480 mono_defaults.corlib, "System", "Byte");
1481 g_assert (mono_defaults.byte_class != 0);
1483 mono_defaults.sbyte_class = mono_class_from_name (
1484 mono_defaults.corlib, "System", "SByte");
1485 g_assert (mono_defaults.sbyte_class != 0);
1487 mono_defaults.int16_class = mono_class_from_name (
1488 mono_defaults.corlib, "System", "Int16");
1489 g_assert (mono_defaults.int16_class != 0);
1491 mono_defaults.uint16_class = mono_class_from_name (
1492 mono_defaults.corlib, "System", "UInt16");
1493 g_assert (mono_defaults.uint16_class != 0);
1495 mono_defaults.int32_class = mono_class_from_name (
1496 mono_defaults.corlib, "System", "Int32");
1497 g_assert (mono_defaults.int32_class != 0);
1499 mono_defaults.uint32_class = mono_class_from_name (
1500 mono_defaults.corlib, "System", "UInt32");
1501 g_assert (mono_defaults.uint32_class != 0);
1503 mono_defaults.uint_class = mono_class_from_name (
1504 mono_defaults.corlib, "System", "UIntPtr");
1505 g_assert (mono_defaults.uint_class != 0);
1507 mono_defaults.int_class = mono_class_from_name (
1508 mono_defaults.corlib, "System", "IntPtr");
1509 g_assert (mono_defaults.int_class != 0);
1511 mono_defaults.int64_class = mono_class_from_name (
1512 mono_defaults.corlib, "System", "Int64");
1513 g_assert (mono_defaults.int64_class != 0);
1515 mono_defaults.uint64_class = mono_class_from_name (
1516 mono_defaults.corlib, "System", "UInt64");
1517 g_assert (mono_defaults.uint64_class != 0);
1519 mono_defaults.single_class = mono_class_from_name (
1520 mono_defaults.corlib, "System", "Single");
1521 g_assert (mono_defaults.single_class != 0);
1523 mono_defaults.double_class = mono_class_from_name (
1524 mono_defaults.corlib, "System", "Double");
1525 g_assert (mono_defaults.double_class != 0);
1527 mono_defaults.char_class = mono_class_from_name (
1528 mono_defaults.corlib, "System", "Char");
1529 g_assert (mono_defaults.char_class != 0);
1531 mono_defaults.string_class = mono_class_from_name (
1532 mono_defaults.corlib, "System", "String");
1533 g_assert (mono_defaults.string_class != 0);
1535 mono_defaults.enum_class = mono_class_from_name (
1536 mono_defaults.corlib, "System", "Enum");
1537 g_assert (mono_defaults.enum_class != 0);
1539 mono_defaults.array_class = mono_class_from_name (
1540 mono_defaults.corlib, "System", "Array");
1541 g_assert (mono_defaults.array_class != 0);
1543 mono_defaults.delegate_class = mono_class_from_name (
1544 mono_defaults.corlib, "System", "Delegate");
1545 g_assert (mono_defaults.delegate_class != 0 );
1547 mono_defaults.multicastdelegate_class = mono_class_from_name (
1548 mono_defaults.corlib, "System", "MulticastDelegate");
1549 g_assert (mono_defaults.multicastdelegate_class != 0 );
1551 mono_defaults.asyncresult_class = mono_class_from_name (
1552 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1554 g_assert (mono_defaults.asyncresult_class != 0 );
1556 mono_defaults.manualresetevent_class = mono_class_from_name (
1557 mono_defaults.corlib, "System.Threading", "ManualResetEvent");
1558 g_assert (mono_defaults.manualresetevent_class != 0 );
1560 mono_defaults.typehandle_class = mono_class_from_name (
1561 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1562 g_assert (mono_defaults.typehandle_class != 0);
1564 mono_defaults.methodhandle_class = mono_class_from_name (
1565 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1566 g_assert (mono_defaults.methodhandle_class != 0);
1568 mono_defaults.fieldhandle_class = mono_class_from_name (
1569 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1570 g_assert (mono_defaults.fieldhandle_class != 0);
1572 mono_defaults.systemtype_class = mono_class_from_name (
1573 mono_defaults.corlib, "System", "Type");
1574 g_assert (mono_defaults.systemtype_class != 0);
1576 mono_defaults.monotype_class = mono_class_from_name (
1577 mono_defaults.corlib, "System", "MonoType");
1578 g_assert (mono_defaults.monotype_class != 0);
1580 mono_defaults.exception_class = mono_class_from_name (
1581 mono_defaults.corlib, "System", "Exception");
1582 g_assert (mono_defaults.exception_class != 0);
1584 mono_defaults.threadabortexception_class = mono_class_from_name (
1585 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1586 g_assert (mono_defaults.threadabortexception_class != 0);
1588 mono_defaults.thread_class = mono_class_from_name (
1589 mono_defaults.corlib, "System.Threading", "Thread");
1590 g_assert (mono_defaults.thread_class != 0);
1592 mono_defaults.internal_thread_class = mono_class_from_name (
1593 mono_defaults.corlib, "System.Threading", "InternalThread");
1594 if (!mono_defaults.internal_thread_class) {
1595 /* This can happen with an old mscorlib */
1596 fprintf (stderr, "Corlib too old for this runtime.\n");
1597 fprintf (stderr, "Loaded from: %s\n",
1598 mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown");
1602 mono_defaults.appdomain_class = mono_class_from_name (
1603 mono_defaults.corlib, "System", "AppDomain");
1604 g_assert (mono_defaults.appdomain_class != 0);
1606 mono_defaults.transparent_proxy_class = mono_class_from_name (
1607 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1608 g_assert (mono_defaults.transparent_proxy_class != 0);
1610 mono_defaults.real_proxy_class = mono_class_from_name (
1611 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1612 g_assert (mono_defaults.real_proxy_class != 0);
1614 mono_defaults.mono_method_message_class = mono_class_from_name (
1615 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1616 g_assert (mono_defaults.mono_method_message_class != 0);
1618 mono_defaults.field_info_class = mono_class_from_name (
1619 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1620 g_assert (mono_defaults.field_info_class != 0);
1622 mono_defaults.method_info_class = mono_class_from_name (
1623 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1624 g_assert (mono_defaults.method_info_class != 0);
1626 mono_defaults.stringbuilder_class = mono_class_from_name (
1627 mono_defaults.corlib, "System.Text", "StringBuilder");
1628 g_assert (mono_defaults.stringbuilder_class != 0);
1630 mono_defaults.math_class = mono_class_from_name (
1631 mono_defaults.corlib, "System", "Math");
1632 g_assert (mono_defaults.math_class != 0);
1634 mono_defaults.stack_frame_class = mono_class_from_name (
1635 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1636 g_assert (mono_defaults.stack_frame_class != 0);
1638 mono_defaults.stack_trace_class = mono_class_from_name (
1639 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1640 g_assert (mono_defaults.stack_trace_class != 0);
1642 mono_defaults.marshal_class = mono_class_from_name (
1643 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1644 g_assert (mono_defaults.marshal_class != 0);
1646 mono_defaults.iserializeable_class = mono_class_from_name (
1647 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
1648 g_assert (mono_defaults.iserializeable_class != 0);
1650 mono_defaults.serializationinfo_class = mono_class_from_name (
1651 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
1652 g_assert (mono_defaults.serializationinfo_class != 0);
1654 mono_defaults.streamingcontext_class = mono_class_from_name (
1655 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
1656 g_assert (mono_defaults.streamingcontext_class != 0);
1658 mono_defaults.typed_reference_class = mono_class_from_name (
1659 mono_defaults.corlib, "System", "TypedReference");
1660 g_assert (mono_defaults.typed_reference_class != 0);
1662 mono_defaults.argumenthandle_class = mono_class_from_name (
1663 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1664 g_assert (mono_defaults.argumenthandle_class != 0);
1666 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1667 mono_defaults.corlib, "System", "MarshalByRefObject");
1668 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1670 mono_defaults.monitor_class = mono_class_from_name (
1671 mono_defaults.corlib, "System.Threading", "Monitor");
1672 g_assert (mono_defaults.monitor_class != 0);
1674 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1675 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1676 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1678 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1679 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1681 mono_defaults.executioncontext_class = mono_class_from_name (
1682 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1684 mono_defaults.internals_visible_class = mono_class_from_name (
1685 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1687 mono_defaults.critical_finalizer_object = mono_class_from_name (
1688 mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
1691 * mscorlib needs a little help, only now it can load its friends list (after we have
1692 * loaded the InternalsVisibleToAttribute), load it now
1694 mono_assembly_load_friends (ass);
1696 mono_defaults.safehandle_class = mono_class_from_name (
1697 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1699 mono_defaults.handleref_class = mono_class_from_name (
1700 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1702 mono_defaults.attribute_class = mono_class_from_name (
1703 mono_defaults.corlib, "System", "Attribute");
1705 mono_defaults.customattribute_data_class = mono_class_from_name (
1706 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1708 /* these are initialized lazily when COM features are used */
1710 mono_defaults.variant_class = NULL;
1711 mono_defaults.com_object_class = NULL;
1712 mono_defaults.com_interop_proxy_class = NULL;
1713 mono_defaults.iunknown_class = NULL;
1714 mono_defaults.idispatch_class = NULL;
1717 mono_class_init (mono_defaults.array_class);
1718 mono_defaults.generic_nullable_class = mono_class_from_name (
1719 mono_defaults.corlib, "System", "Nullable`1");
1720 mono_defaults.generic_ilist_class = mono_class_from_name (
1721 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1722 mono_defaults.generic_ireadonlylist_class = mono_class_from_name (
1723 mono_defaults.corlib, "System.Collections.Generic", "IReadOnlyList`1");
1725 domain->friendly_name = g_path_get_basename (filename);
1727 _mono_debug_init_corlib (domain);
1735 * Creates the initial application domain and initializes the mono_defaults
1737 * This function is guaranteed to not run any IL code.
1738 * The runtime is initialized using the default runtime version.
1740 * Returns: the initial domain.
1743 mono_init (const char *domain_name)
1745 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1749 * mono_init_from_assembly:
1750 * @domain_name: name to give to the initial domain
1751 * @filename: filename to load on startup
1753 * Used by the runtime, users should use mono_jit_init instead.
1755 * Creates the initial application domain and initializes the mono_defaults
1757 * This function is guaranteed to not run any IL code.
1758 * The runtime is initialized using the runtime version required by the
1759 * provided executable. The version is determined by looking at the exe
1760 * configuration file and the version PE field)
1762 * Returns: the initial domain.
1765 mono_init_from_assembly (const char *domain_name, const char *filename)
1767 return mono_init_internal (domain_name, filename, NULL);
1771 * mono_init_version:
1773 * Used by the runtime, users should use mono_jit_init instead.
1775 * Creates the initial application domain and initializes the mono_defaults
1778 * This function is guaranteed to not run any IL code.
1779 * The runtime is initialized using the provided rutime version.
1781 * Returns: the initial domain.
1784 mono_init_version (const char *domain_name, const char *version)
1786 return mono_init_internal (domain_name, NULL, version);
1791 * mono_init_com_types:
1793 * Initializes all types needed for COM Interop in mono_defaults structure.
1796 mono_init_com_types (void)
1798 static gboolean initialized = FALSE;
1803 /* FIXME: do I need some threading protection here */
1805 g_assert (mono_defaults.corlib);
1807 mono_defaults.variant_class = mono_class_from_name (
1808 mono_defaults.corlib, "System", "Variant");
1809 g_assert (mono_defaults.variant_class != 0);
1811 mono_defaults.com_object_class = mono_class_from_name (
1812 mono_defaults.corlib, "System", "__ComObject");
1813 g_assert (mono_defaults.com_object_class != 0);
1815 mono_defaults.com_interop_proxy_class = mono_class_from_name (
1816 mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
1817 g_assert (mono_defaults.com_interop_proxy_class != 0);
1819 mono_defaults.iunknown_class = mono_class_from_name (
1820 mono_defaults.corlib, "Mono.Interop", "IUnknown");
1821 g_assert (mono_defaults.iunknown_class != 0);
1823 mono_defaults.idispatch_class = mono_class_from_name (
1824 mono_defaults.corlib, "Mono.Interop", "IDispatch");
1825 g_assert (mono_defaults.idispatch_class != 0);
1829 #endif /*DISABLE_COM*/
1834 * Cleans up all metadata modules.
1839 mono_close_exe_image ();
1841 mono_defaults.corlib = NULL;
1843 mono_config_cleanup ();
1844 mono_loader_cleanup ();
1845 mono_classes_cleanup ();
1846 mono_assemblies_cleanup ();
1847 mono_images_cleanup ();
1848 mono_debug_cleanup ();
1849 mono_metadata_cleanup ();
1850 #ifdef USE_JUMP_TABLES
1851 mono_jumptable_cleanup ();
1855 mono_native_tls_free (appdomain_thread_id);
1856 DeleteCriticalSection (&appdomains_mutex);
1864 mono_close_exe_image (void)
1867 mono_image_close (exe_image);
1871 * mono_get_root_domain:
1873 * The root AppDomain is the initial domain created by the runtime when it is
1874 * initialized. Programs execute on this AppDomain, but can create new ones
1875 * later. Currently there is no unmanaged API to create new AppDomains, this
1876 * must be done from managed code.
1878 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1881 mono_get_root_domain (void)
1883 return mono_root_domain;
1889 * Returns: the current domain, to obtain the root domain use
1890 * mono_get_root_domain().
1895 return GET_APPDOMAIN ();
1899 mono_domain_unset (void)
1901 SET_APPDOMAIN (NULL);
1905 mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception)
1907 MonoInternalThread *thread;
1909 if (mono_domain_get () == domain)
1912 SET_APPDOMAIN (domain);
1913 SET_APPCONTEXT (domain->default_context);
1915 if (migrate_exception) {
1916 thread = mono_thread_internal_current ();
1917 if (!thread->abort_exc)
1920 g_assert (thread->abort_exc->object.vtable->domain != domain);
1921 MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
1922 g_assert (thread->abort_exc->object.vtable->domain == domain);
1927 * mono_domain_set_internal:
1928 * @domain: the new domain
1930 * Sets the current domain to @domain.
1933 mono_domain_set_internal (MonoDomain *domain)
1935 mono_domain_set_internal_with_options (domain, TRUE);
1939 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1945 * Create a copy of the data to avoid calling the user callback
1946 * inside the lock because that could lead to deadlocks.
1947 * We can do this because this function is not perf. critical.
1949 mono_appdomains_lock ();
1950 size = appdomain_list_size;
1951 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1952 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1953 mono_appdomains_unlock ();
1955 for (i = 0; i < size; ++i) {
1957 func (copy [i], user_data);
1960 mono_gc_free_fixed (copy);
1964 * mono_domain_assembly_open:
1965 * @domain: the application domain
1966 * @name: file name of the assembly
1968 * fixme: maybe we should integrate this with mono_assembly_open ??
1971 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1973 MonoDomain *current;
1977 mono_domain_assemblies_lock (domain);
1978 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1980 if (strcmp (name, ass->aname.name) == 0) {
1981 mono_domain_assemblies_unlock (domain);
1985 mono_domain_assemblies_unlock (domain);
1987 if (domain != mono_domain_get ()) {
1988 current = mono_domain_get ();
1990 mono_domain_set (domain, FALSE);
1991 ass = mono_assembly_open (name, NULL);
1992 mono_domain_set (current, FALSE);
1994 ass = mono_assembly_open (name, NULL);
2001 unregister_vtable_reflection_type (MonoVTable *vtable)
2003 MonoObject *type = vtable->type;
2005 if (type->vtable->klass != mono_defaults.monotype_class)
2006 MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type);
2010 mono_domain_free (MonoDomain *domain, gboolean force)
2012 int code_size, code_alloc;
2014 if ((domain == mono_root_domain) && !force) {
2015 g_warning ("cant unload root domain");
2019 if (mono_dont_free_domains)
2022 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
2024 mono_debug_domain_unload (domain);
2026 mono_appdomains_lock ();
2027 appdomains_list [domain->domain_id] = NULL;
2028 mono_appdomains_unlock ();
2030 /* must do this early as it accesses fields and types */
2031 if (domain->special_static_fields) {
2032 mono_alloc_special_static_data_free (domain->special_static_fields);
2033 g_hash_table_destroy (domain->special_static_fields);
2034 domain->special_static_fields = NULL;
2038 * We must destroy all these hash tables here because they
2039 * contain references to managed objects belonging to the
2040 * domain. Once we let the GC clear the domain there must be
2041 * no more such references, or we'll crash if a collection
2044 mono_g_hash_table_destroy (domain->ldstr_table);
2045 domain->ldstr_table = NULL;
2047 mono_g_hash_table_destroy (domain->env);
2050 if (domain->tlsrec_list) {
2051 mono_thread_destroy_domain_tls (domain);
2052 domain->tlsrec_list = NULL;
2055 mono_reflection_cleanup_domain (domain);
2057 if (domain->type_hash) {
2058 mono_g_hash_table_destroy (domain->type_hash);
2059 domain->type_hash = NULL;
2061 if (domain->type_init_exception_hash) {
2062 mono_g_hash_table_destroy (domain->type_init_exception_hash);
2063 domain->type_init_exception_hash = NULL;
2066 if (domain->class_vtable_array) {
2068 for (i = 0; i < domain->class_vtable_array->len; ++i)
2069 unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i));
2072 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
2073 MonoAssembly *ass = tmp->data;
2074 mono_assembly_release_gc_roots (ass);
2077 /* This needs to be done before closing assemblies */
2078 mono_gc_clear_domain (domain);
2080 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
2081 MonoAssembly *ass = tmp->data;
2082 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s[%p], assembly %s[%p], ref_count=%d", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count);
2083 if (!mono_assembly_close_except_image_pools (ass))
2087 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
2088 MonoAssembly *ass = tmp->data;
2090 mono_assembly_close_finish (ass);
2092 g_slist_free (domain->domain_assemblies);
2093 domain->domain_assemblies = NULL;
2096 * Send this after the assemblies have been unloaded and the domain is still in a
2099 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
2101 if (free_domain_hook)
2102 free_domain_hook (domain);
2104 /* FIXME: free delegate_hash_table when it's used */
2105 if (domain->search_path) {
2106 g_strfreev (domain->search_path);
2107 domain->search_path = NULL;
2109 domain->create_proxy_for_type_method = NULL;
2110 domain->private_invoke_method = NULL;
2111 domain->default_context = NULL;
2112 domain->out_of_memory_ex = NULL;
2113 domain->null_reference_ex = NULL;
2114 domain->stack_overflow_ex = NULL;
2115 domain->ephemeron_tombstone = NULL;
2116 domain->entry_assembly = NULL;
2118 g_free (domain->friendly_name);
2119 domain->friendly_name = NULL;
2120 g_ptr_array_free (domain->class_vtable_array, TRUE);
2121 domain->class_vtable_array = NULL;
2122 g_hash_table_destroy (domain->proxy_vtable_hash);
2123 domain->proxy_vtable_hash = NULL;
2124 if (domain->static_data_array) {
2125 mono_gc_free_fixed (domain->static_data_array);
2126 domain->static_data_array = NULL;
2128 mono_internal_hash_table_destroy (&domain->jit_code_hash);
2131 * There might still be jit info tables of this domain which
2132 * are not freed. Since the domain cannot be in use anymore,
2133 * this will free them.
2135 mono_thread_hazardous_try_free_all ();
2136 g_assert (domain->num_jit_info_tables == 1);
2137 jit_info_table_free (domain->jit_info_table);
2138 domain->jit_info_table = NULL;
2139 g_assert (!domain->jit_info_free_queue);
2141 /* collect statistics */
2142 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
2143 total_domain_code_alloc += code_alloc;
2144 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
2145 max_domain_code_size = MAX (max_domain_code_size, code_size);
2147 #ifdef DEBUG_DOMAIN_UNLOAD
2148 mono_mempool_invalidate (domain->mp);
2149 mono_code_manager_invalidate (domain->code_mp);
2151 #ifndef DISABLE_PERFCOUNTERS
2152 mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
2154 mono_mempool_destroy (domain->mp);
2156 mono_code_manager_destroy (domain->code_mp);
2157 domain->code_mp = NULL;
2160 g_hash_table_destroy (domain->finalizable_objects_hash);
2161 domain->finalizable_objects_hash = NULL;
2162 if (domain->method_rgctx_hash) {
2163 g_hash_table_destroy (domain->method_rgctx_hash);
2164 domain->method_rgctx_hash = NULL;
2166 if (domain->generic_virtual_cases) {
2167 g_hash_table_destroy (domain->generic_virtual_cases);
2168 domain->generic_virtual_cases = NULL;
2170 if (domain->generic_virtual_thunks) {
2171 g_hash_table_destroy (domain->generic_virtual_thunks);
2172 domain->generic_virtual_thunks = NULL;
2174 if (domain->ftnptrs_hash) {
2175 g_hash_table_destroy (domain->ftnptrs_hash);
2176 domain->ftnptrs_hash = NULL;
2179 DeleteCriticalSection (&domain->finalizable_objects_hash_lock);
2180 DeleteCriticalSection (&domain->assemblies_lock);
2181 DeleteCriticalSection (&domain->jit_code_hash_lock);
2182 DeleteCriticalSection (&domain->lock);
2183 domain->setup = NULL;
2185 mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
2187 /* FIXME: anything else required ? */
2189 mono_gc_free_fixed (domain);
2191 #ifndef DISABLE_PERFCOUNTERS
2192 mono_perfcounters->loader_appdomains--;
2195 if (domain == mono_root_domain)
2196 mono_root_domain = NULL;
2200 * mono_domain_get_id:
2203 * Returns: the a domain for a specific domain id.
2206 mono_domain_get_by_id (gint32 domainid)
2208 MonoDomain * domain;
2210 mono_appdomains_lock ();
2211 if (domainid < appdomain_list_size)
2212 domain = appdomains_list [domainid];
2215 mono_appdomains_unlock ();
2221 mono_domain_get_id (MonoDomain *domain)
2223 return domain->domain_id;
2227 * mono_domain_alloc:
2229 * LOCKING: Acquires the domain lock.
2232 mono_domain_alloc (MonoDomain *domain, guint size)
2236 mono_domain_lock (domain);
2237 #ifndef DISABLE_PERFCOUNTERS
2238 mono_perfcounters->loader_bytes += size;
2240 res = mono_mempool_alloc (domain->mp, size);
2241 mono_domain_unlock (domain);
2247 * mono_domain_alloc0:
2249 * LOCKING: Acquires the domain lock.
2252 mono_domain_alloc0 (MonoDomain *domain, guint size)
2256 mono_domain_lock (domain);
2257 #ifndef DISABLE_PERFCOUNTERS
2258 mono_perfcounters->loader_bytes += size;
2260 res = mono_mempool_alloc0 (domain->mp, size);
2261 mono_domain_unlock (domain);
2267 * mono_domain_code_reserve:
2269 * LOCKING: Acquires the domain lock.
2272 mono_domain_code_reserve (MonoDomain *domain, int size)
2276 mono_domain_lock (domain);
2277 res = mono_code_manager_reserve (domain->code_mp, size);
2278 mono_domain_unlock (domain);
2284 * mono_domain_code_reserve_align:
2286 * LOCKING: Acquires the domain lock.
2289 mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment)
2293 mono_domain_lock (domain);
2294 res = mono_code_manager_reserve_align (domain->code_mp, size, alignment);
2295 mono_domain_unlock (domain);
2301 * mono_domain_code_commit:
2303 * LOCKING: Acquires the domain lock.
2306 mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize)
2308 mono_domain_lock (domain);
2309 mono_code_manager_commit (domain->code_mp, data, size, newsize);
2310 mono_domain_unlock (domain);
2313 #if defined(__native_client_codegen__) && defined(__native_client__)
2315 * Given the temporary buffer (allocated by mono_domain_code_reserve) into which
2316 * we are generating code, return a pointer to the destination in the dynamic
2317 * code segment into which the code will be copied when mono_domain_code_commit
2319 * LOCKING: Acquires the domain lock.
2322 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2325 mono_domain_lock (domain);
2326 dest = nacl_code_manager_get_code_dest (domain->code_mp, data);
2327 mono_domain_unlock (domain);
2332 * Convenience function which calls mono_domain_code_commit to validate and copy
2333 * the code. The caller sets *buf_base and *buf_size to the start and size of
2334 * the buffer (allocated by mono_domain_code_reserve), and *code_end to the byte
2335 * after the last instruction byte. On return, *buf_base will point to the start
2336 * of the copied in the code segment, and *code_end will point after the end of
2340 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2342 guint8 *tmp = nacl_domain_get_code_dest (domain, *buf_base);
2343 mono_domain_code_commit (domain, *buf_base, buf_size, *code_end - *buf_base);
2344 *code_end = tmp + (*code_end - *buf_base);
2350 /* no-op versions of Native Client functions */
2353 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2359 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2366 * mono_domain_code_foreach:
2367 * Iterate over the code thunks of the code manager of @domain.
2369 * The @func callback MUST not take any locks. If it really needs to, it must respect
2370 * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety
2371 * LOCKING: Acquires the domain lock.
2375 mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data)
2377 mono_domain_lock (domain);
2378 mono_code_manager_foreach (domain->code_mp, func, user_data);
2379 mono_domain_unlock (domain);
2384 mono_context_set (MonoAppContext * new_context)
2386 SET_APPCONTEXT (new_context);
2390 mono_context_get (void)
2392 return GET_APPCONTEXT ();
2395 /* LOCKING: the caller holds the lock for this domain */
2397 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
2399 /* The first entry in the array is the index of the next free slot
2400 * and the total size of the array
2403 if (domain->static_data_array) {
2404 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
2405 next = GPOINTER_TO_INT (domain->static_data_array [0]);
2407 /* 'data' is allocated by alloc_fixed */
2408 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2));
2409 mono_gc_memmove (new_array, domain->static_data_array, sizeof (gpointer) * size);
2411 new_array [1] = GINT_TO_POINTER (size);
2412 mono_gc_free_fixed (domain->static_data_array);
2413 domain->static_data_array = new_array;
2417 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, MONO_GC_ROOT_DESCR_FOR_FIXED (size));
2419 new_array [0] = GINT_TO_POINTER (next);
2420 new_array [1] = GINT_TO_POINTER (size);
2421 domain->static_data_array = new_array;
2423 domain->static_data_array [next++] = data;
2424 domain->static_data_array [0] = GINT_TO_POINTER (next);
2428 mono_get_corlib (void)
2430 return mono_defaults.corlib;
2434 mono_get_object_class (void)
2436 return mono_defaults.object_class;
2440 mono_get_byte_class (void)
2442 return mono_defaults.byte_class;
2446 mono_get_void_class (void)
2448 return mono_defaults.void_class;
2452 mono_get_boolean_class (void)
2454 return mono_defaults.boolean_class;
2458 mono_get_sbyte_class (void)
2460 return mono_defaults.sbyte_class;
2464 mono_get_int16_class (void)
2466 return mono_defaults.int16_class;
2470 mono_get_uint16_class (void)
2472 return mono_defaults.uint16_class;
2476 mono_get_int32_class (void)
2478 return mono_defaults.int32_class;
2482 mono_get_uint32_class (void)
2484 return mono_defaults.uint32_class;
2488 mono_get_intptr_class (void)
2490 return mono_defaults.int_class;
2494 mono_get_uintptr_class (void)
2496 return mono_defaults.uint_class;
2500 mono_get_int64_class (void)
2502 return mono_defaults.int64_class;
2506 mono_get_uint64_class (void)
2508 return mono_defaults.uint64_class;
2512 mono_get_single_class (void)
2514 return mono_defaults.single_class;
2518 mono_get_double_class (void)
2520 return mono_defaults.double_class;
2524 mono_get_char_class (void)
2526 return mono_defaults.char_class;
2530 mono_get_string_class (void)
2532 return mono_defaults.string_class;
2536 mono_get_enum_class (void)
2538 return mono_defaults.enum_class;
2542 mono_get_array_class (void)
2544 return mono_defaults.array_class;
2548 mono_get_thread_class (void)
2550 return mono_defaults.thread_class;
2554 mono_get_exception_class (void)
2556 return mono_defaults.exception_class;
2560 static char* get_attribute_value (const gchar **attribute_names,
2561 const gchar **attribute_values,
2562 const char *att_name)
2565 for (n=0; attribute_names[n] != NULL; n++) {
2566 if (strcmp (attribute_names[n], att_name) == 0)
2567 return g_strdup (attribute_values[n]);
2572 static void start_element (GMarkupParseContext *context,
2573 const gchar *element_name,
2574 const gchar **attribute_names,
2575 const gchar **attribute_values,
2579 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2581 if (strcmp (element_name, "configuration") == 0) {
2582 app_config->configuration_count++;
2585 if (strcmp (element_name, "startup") == 0) {
2586 app_config->startup_count++;
2590 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2593 if (strcmp (element_name, "requiredRuntime") == 0) {
2594 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2595 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2596 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2597 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2601 static void end_element (GMarkupParseContext *context,
2602 const gchar *element_name,
2606 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2608 if (strcmp (element_name, "configuration") == 0) {
2609 app_config->configuration_count--;
2610 } else if (strcmp (element_name, "startup") == 0) {
2611 app_config->startup_count--;
2615 static const GMarkupParser
2624 static AppConfigInfo *
2625 app_config_parse (const char *exe_filename)
2627 AppConfigInfo *app_config;
2628 GMarkupParseContext *context;
2631 const char *bundled_config;
2632 char *config_filename;
2634 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2636 if (bundled_config) {
2637 text = g_strdup (bundled_config);
2638 len = strlen (text);
2640 config_filename = g_strconcat (exe_filename, ".config", NULL);
2642 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2643 g_free (config_filename);
2646 g_free (config_filename);
2649 app_config = g_new0 (AppConfigInfo, 1);
2651 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2652 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2653 g_markup_parse_context_end_parse (context, NULL);
2655 g_markup_parse_context_free (context);
2661 app_config_free (AppConfigInfo* app_config)
2664 GSList *list = app_config->supported_runtimes;
2665 while (list != NULL) {
2666 rt = (char*)list->data;
2668 list = g_slist_next (list);
2670 g_slist_free (app_config->supported_runtimes);
2671 g_free (app_config->required_runtime);
2672 g_free (app_config);
2676 static const MonoRuntimeInfo*
2677 get_runtime_by_version (const char *version)
2680 int max = G_N_ELEMENTS (supported_runtimes);
2686 for (n=0; n<max; n++) {
2687 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2688 return &supported_runtimes[n];
2691 vlen = strlen (version);
2692 if (vlen >= 4 && version [1] - '0' >= 4) {
2693 for (n=0; n<max; n++) {
2694 if (strncmp (version, supported_runtimes[n].runtime_version, 4) == 0)
2695 return &supported_runtimes[n];
2703 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2705 AppConfigInfo* app_config;
2707 const MonoRuntimeInfo* runtime = NULL;
2708 MonoImage *image = NULL;
2710 app_config = app_config_parse (exe_file);
2712 if (app_config != NULL) {
2713 /* Check supportedRuntime elements, if none is supported, fail.
2714 * If there are no such elements, look for a requiredRuntime element.
2716 if (app_config->supported_runtimes != NULL) {
2718 GSList *list = app_config->supported_runtimes;
2719 while (list != NULL) {
2720 version = (char*) list->data;
2721 runtime = get_runtime_by_version (version);
2722 if (runtime != NULL)
2723 runtimes [n++] = runtime;
2724 list = g_slist_next (list);
2726 runtimes [n] = NULL;
2727 app_config_free (app_config);
2731 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2732 if (app_config->required_runtime != NULL) {
2733 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2734 runtimes [1] = NULL;
2735 app_config_free (app_config);
2738 app_config_free (app_config);
2741 /* Look for a runtime with the exact version */
2742 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2745 image = mono_image_open (exe_file, NULL);
2747 if (image == NULL) {
2748 /* The image is wrong or the file was not found. In this case return
2749 * a default runtime and leave to the initialization method the work of
2750 * reporting the error.
2752 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2753 runtimes [1] = NULL;
2759 runtimes [0] = get_runtime_by_version (image->version);
2760 runtimes [1] = NULL;
2765 * mono_get_runtime_info:
2767 * Returns: the version of the current runtime instance.
2769 const MonoRuntimeInfo*
2770 mono_get_runtime_info (void)
2772 return current_runtime;
2776 mono_debugger_check_runtime_version (const char *filename)
2778 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2779 const MonoRuntimeInfo *rinfo;
2782 get_runtimes_from_exe (filename, &image, runtimes);
2783 rinfo = runtimes [0];
2786 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2788 if (rinfo != current_runtime)
2789 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2790 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2791 filename, rinfo->runtime_version);
2797 * mono_framework_version:
2799 * Return the major version of the framework curently executing.
2802 mono_framework_version (void)
2804 return current_runtime->framework_version [0] - '0';