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 <mono/metadata/runtime.h>
39 #include <metadata/threads.h>
40 #include <metadata/profiler-private.h>
41 #include <mono/metadata/coree.h>
43 /* #define DEBUG_DOMAIN_UNLOAD */
45 /* we need to use both the Tls* functions and __thread because
46 * some archs may generate faster jit code with one meachanism
47 * or the other (we used to do it because tls slots were GC-tracked,
48 * but we can't depend on this).
50 static MonoNativeTlsKey appdomain_thread_id;
52 #ifdef MONO_HAVE_FAST_TLS
54 MONO_FAST_TLS_DECLARE(tls_appdomain);
56 #define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain))
58 #define SET_APPDOMAIN(x) do { \
59 MONO_FAST_TLS_SET (tls_appdomain,x); \
60 mono_native_tls_set_value (appdomain_thread_id, x); \
61 mono_gc_set_current_thread_appdomain (x); \
64 #else /* !MONO_HAVE_FAST_TLS */
66 #define GET_APPDOMAIN() ((MonoDomain *)mono_native_tls_get_value (appdomain_thread_id))
67 #define SET_APPDOMAIN(x) do { \
68 mono_native_tls_set_value (appdomain_thread_id, x); \
69 mono_gc_set_current_thread_appdomain (x); \
74 #define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext)
75 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x))
77 static guint16 appdomain_list_size = 0;
78 static guint16 appdomain_next = 0;
79 static MonoDomain **appdomains_list = NULL;
80 static MonoImage *exe_image;
82 gboolean mono_dont_free_domains;
84 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
85 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
86 static CRITICAL_SECTION appdomains_mutex;
88 static MonoDomain *mono_root_domain = NULL;
91 static int max_domain_code_size = 0;
92 static int max_domain_code_alloc = 0;
93 static int total_domain_code_alloc = 0;
95 /* AppConfigInfo: Information about runtime versions supported by an
99 GSList *supported_runtimes;
100 char *required_runtime;
101 int configuration_count;
106 * AotModuleInfo: Contains information about AOT modules.
113 static const MonoRuntimeInfo *current_runtime = NULL;
115 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
118 * Contains information about AOT loaded code.
120 static MonoAotModuleInfoTable *aot_modules = NULL;
122 /* This is the list of runtime versions supported by this JIT.
124 static const MonoRuntimeInfo supported_runtimes[] = {
125 {"v2.0.50215","2.0", { {2,0,0,0}, { 8,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
126 {"v2.0.50727","2.0", { {2,0,0,0}, { 8,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
127 {"v4.0.30319","4.5", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
128 {"v4.0.30128","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
129 {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
130 {"moonlight", "2.1", { {2,0,5,0}, { 9,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
134 /* The stable runtime version */
135 #define DEFAULT_RUNTIME_VERSION "v2.0.50727"
137 /* Callbacks installed by the JIT */
138 static MonoCreateDomainFunc create_domain_hook;
139 static MonoFreeDomainFunc free_domain_hook;
141 /* This is intentionally not in the header file, so people don't misuse it. */
142 extern void _mono_debug_init_corlib (MonoDomain *domain);
145 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
147 static const MonoRuntimeInfo*
148 get_runtime_by_version (const char *version);
151 mono_jit_info_find_aot_module (guint8* addr);
154 mono_domain_get_tls_key (void)
156 return appdomain_thread_id;
160 mono_domain_get_tls_offset (void)
163 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
164 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
169 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
170 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
171 #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)
173 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
174 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
176 #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
177 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
179 #define JIT_INFO_TABLE_HAZARD_INDEX 0
180 #define JIT_INFO_HAZARD_INDEX 1
183 jit_info_table_num_elements (MonoJitInfoTable *table)
186 int num_elements = 0;
188 for (i = 0; i < table->num_chunks; ++i) {
189 MonoJitInfoTableChunk *chunk = table->chunks [i];
190 int chunk_num_elements = chunk->num_elements;
193 for (j = 0; j < chunk_num_elements; ++j) {
194 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
202 static MonoJitInfoTableChunk*
203 jit_info_table_new_chunk (void)
205 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
211 static MonoJitInfoTable *
212 jit_info_table_new (MonoDomain *domain)
214 MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
216 table->domain = domain;
217 table->num_chunks = 1;
218 table->chunks [0] = jit_info_table_new_chunk ();
224 jit_info_table_free (MonoJitInfoTable *table)
227 int num_chunks = table->num_chunks;
228 MonoDomain *domain = table->domain;
230 mono_domain_lock (domain);
232 table->domain->num_jit_info_tables--;
233 if (table->domain->num_jit_info_tables <= 1) {
236 for (list = table->domain->jit_info_free_queue; list; list = list->next)
239 g_slist_free (table->domain->jit_info_free_queue);
240 table->domain->jit_info_free_queue = NULL;
243 /* At this point we assume that there are no other threads
244 still accessing the table, so we don't have to worry about
245 hazardous pointers. */
247 for (i = 0; i < num_chunks; ++i) {
248 MonoJitInfoTableChunk *chunk = table->chunks [i];
252 if (--chunk->refcount > 0)
255 num_elements = chunk->num_elements;
256 for (j = 0; j < num_elements; ++j) {
257 MonoJitInfo *ji = chunk->data [j];
259 if (IS_JIT_INFO_TOMBSTONE (ji))
266 mono_domain_unlock (domain);
271 /* The jit_info_table is sorted in ascending order by the end
272 * addresses of the compiled methods. The reason why we have to do
273 * this is that once we introduce tombstones, it becomes possible for
274 * code ranges to overlap, and if we sort by code start and insert at
275 * the back of the table, we cannot guarantee that we won't overlook
278 * There are actually two possible ways to do the sorting and
279 * inserting which work with our lock-free mechanism:
281 * 1. Sort by start address and insert at the front. When looking for
282 * an entry, find the last one with a start address lower than the one
283 * you're looking for, then work your way to the front of the table.
285 * 2. Sort by end address and insert at the back. When looking for an
286 * entry, find the first one with an end address higher than the one
287 * you're looking for, then work your way to the end of the table.
289 * We chose the latter out of convenience.
292 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
294 int left = 0, right = table->num_chunks;
296 g_assert (left < right);
299 int pos = (left + right) / 2;
300 MonoJitInfoTableChunk *chunk = table->chunks [pos];
302 if (addr < chunk->last_code_end)
306 } while (left < right);
307 g_assert (left == right);
309 if (left >= table->num_chunks)
310 return table->num_chunks - 1;
315 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
317 int left = 0, right = chunk->num_elements;
319 while (left < right) {
320 int pos = (left + right) / 2;
321 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
322 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
329 g_assert (left == right);
335 * mono_jit_info_table_find_internal:
337 * If TRY_AOT is FALSE, avoid loading information for missing methods from AOT images, which is currently not async safe.
338 * In this case, only those AOT methods will be found whose jit info is already loaded.
341 mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot)
343 MonoJitInfoTable *table;
346 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
349 ++mono_stats.jit_info_table_lookup_count;
351 /* First we have to get the domain's jit_info_table. This is
352 complicated by the fact that a writer might substitute a
353 new table and free the old one. What the writer guarantees
354 us is that it looks at the hazard pointers after it has
355 changed the jit_info_table pointer. So, if we guard the
356 table by a hazard pointer and make sure that the pointer is
357 still there after we've made it hazardous, we don't have to
358 worry about the writer freeing the table. */
359 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
361 chunk_pos = jit_info_table_index (table, (gint8*)addr);
362 g_assert (chunk_pos < table->num_chunks);
364 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
366 /* We now have a position that's very close to that of the
367 first element whose end address is higher than the one
368 we're looking for. If we don't have the exact position,
369 then we have a position below that one, so we'll just
370 search upward until we find our element. */
372 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
374 while (pos < chunk->num_elements) {
375 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
379 if (IS_JIT_INFO_TOMBSTONE (ji)) {
380 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
383 if ((gint8*)addr >= (gint8*)ji->code_start
384 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
385 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
386 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
390 /* If we find a non-tombstone element which is already
391 beyond what we're looking for, we have to end the
393 if ((gint8*)addr < (gint8*)ji->code_start)
399 } while (chunk_pos < table->num_chunks);
405 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
406 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
410 /* Maybe its an AOT module */
412 image = mono_jit_info_find_aot_module ((guint8*)addr);
414 ji = jit_info_find_in_aot_func (domain, image, addr);
421 mono_jit_info_table_find (MonoDomain *domain, char *addr)
423 return mono_jit_info_table_find_internal (domain, addr, TRUE);
426 static G_GNUC_UNUSED void
427 jit_info_table_check (MonoJitInfoTable *table)
431 for (i = 0; i < table->num_chunks; ++i) {
432 MonoJitInfoTableChunk *chunk = table->chunks [i];
435 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
436 if (chunk->refcount > 10)
437 printf("warning: chunk refcount is %d\n", chunk->refcount);
438 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
440 for (j = 0; j < chunk->num_elements; ++j) {
441 MonoJitInfo *this = chunk->data [j];
444 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
446 if (j < chunk->num_elements - 1)
447 next = chunk->data [j + 1];
448 else if (i < table->num_chunks - 1) {
451 for (k = i + 1; k < table->num_chunks; ++k)
452 if (table->chunks [k]->num_elements > 0)
455 if (k >= table->num_chunks)
458 g_assert (table->chunks [k]->num_elements > 0);
459 next = table->chunks [k]->data [0];
463 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
468 static MonoJitInfoTable*
469 jit_info_table_realloc (MonoJitInfoTable *old)
472 int num_elements = jit_info_table_num_elements (old);
475 int new_chunk, new_element;
476 MonoJitInfoTable *new;
478 /* number of needed places for elements needed */
479 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
480 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
481 if (num_chunks == 0) {
482 g_assert (num_elements == 0);
483 return jit_info_table_new (old->domain);
485 g_assert (num_chunks > 0);
487 new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
488 new->domain = old->domain;
489 new->num_chunks = num_chunks;
491 for (i = 0; i < num_chunks; ++i)
492 new->chunks [i] = jit_info_table_new_chunk ();
496 for (i = 0; i < old->num_chunks; ++i) {
497 MonoJitInfoTableChunk *chunk = old->chunks [i];
498 int chunk_num_elements = chunk->num_elements;
501 for (j = 0; j < chunk_num_elements; ++j) {
502 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
503 g_assert (new_chunk < num_chunks);
504 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
505 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
506 new->chunks [new_chunk]->num_elements = new_element;
514 if (new_chunk < num_chunks) {
515 g_assert (new_chunk == num_chunks - 1);
516 new->chunks [new_chunk]->num_elements = new_element;
517 g_assert (new->chunks [new_chunk]->num_elements > 0);
520 for (i = 0; i < num_chunks; ++i) {
521 MonoJitInfoTableChunk *chunk = new->chunks [i];
522 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
524 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
531 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
533 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
534 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
536 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
538 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
539 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
541 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
542 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
544 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
545 + new1->data [new1->num_elements - 1]->code_size;
546 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
547 + new2->data [new2->num_elements - 1]->code_size;
553 static MonoJitInfoTable*
554 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
556 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
557 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
560 new_table->domain = table->domain;
561 new_table->num_chunks = table->num_chunks + 1;
564 for (i = 0; i < table->num_chunks; ++i) {
565 if (table->chunks [i] == chunk) {
566 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
569 new_table->chunks [j] = table->chunks [i];
570 ++new_table->chunks [j]->refcount;
575 g_assert (j == new_table->num_chunks);
580 static MonoJitInfoTableChunk*
581 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
583 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
587 for (i = 0; i < old->num_elements; ++i) {
588 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
589 new->data [j++] = old->data [i];
592 new->num_elements = j;
593 if (new->num_elements > 0)
594 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
596 new->last_code_end = old->last_code_end;
601 static MonoJitInfoTable*
602 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
604 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
605 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
608 new_table->domain = table->domain;
609 new_table->num_chunks = table->num_chunks;
612 for (i = 0; i < table->num_chunks; ++i) {
613 if (table->chunks [i] == chunk)
614 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
616 new_table->chunks [j] = table->chunks [i];
617 ++new_table->chunks [j]->refcount;
622 g_assert (j == new_table->num_chunks);
627 /* As we add an element to the table the case can arise that the chunk
628 * to which we need to add is already full. In that case we have to
629 * allocate a new table and do something about that chunk. We have
630 * several strategies:
632 * If the number of elements in the table is below the low watermark
633 * or above the high watermark, we reallocate the whole table.
634 * Otherwise we only concern ourselves with the overflowing chunk:
636 * If there are no tombstones in the chunk then we split the chunk in
637 * two, each half full.
639 * If the chunk does contain tombstones, we just make a new copy of
640 * the chunk without the tombstones, which will have room for at least
641 * the one element we have to add.
643 static MonoJitInfoTable*
644 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
646 int num_elements = jit_info_table_num_elements (table);
649 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
650 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
651 //printf ("reallocing table\n");
652 return jit_info_table_realloc (table);
655 /* count the number of non-tombstone elements in the chunk */
657 for (i = 0; i < chunk->num_elements; ++i) {
658 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
662 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
663 //printf ("splitting chunk\n");
664 return jit_info_table_copy_and_split_chunk (table, chunk);
667 //printf ("purifying chunk\n");
668 return jit_info_table_copy_and_purify_chunk (table, chunk);
671 /* We add elements to the table by first making space for them by
672 * shifting the elements at the back to the right, one at a time.
673 * This results in duplicate entries during the process, but during
674 * all the time the table is in a sorted state. Also, when an element
675 * is replaced by another one, the element that replaces it has an end
676 * address that is equal to or lower than that of the replaced
677 * element. That property is necessary to guarantee that when
678 * searching for an element we end up at a position not higher than
679 * the one we're looking for (i.e. we either find the element directly
680 * or we end up to the left of it).
683 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
685 MonoJitInfoTable *table;
687 MonoJitInfoTableChunk *chunk;
691 g_assert (ji->method != NULL);
693 mono_domain_lock (domain);
695 ++mono_stats.jit_info_table_insert_count;
697 table = domain->jit_info_table;
700 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
701 g_assert (chunk_pos < table->num_chunks);
702 chunk = table->chunks [chunk_pos];
704 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
705 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
707 /* Debugging code, should be removed. */
708 //jit_info_table_check (new_table);
710 domain->jit_info_table = new_table;
711 mono_memory_barrier ();
712 domain->num_jit_info_tables++;
713 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free, TRUE, FALSE);
719 /* Debugging code, should be removed. */
720 //jit_info_table_check (table);
722 num_elements = chunk->num_elements;
724 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
726 /* First we need to size up the chunk by one, by copying the
727 last item, or inserting the first one, if the table is
729 if (num_elements > 0)
730 chunk->data [num_elements] = chunk->data [num_elements - 1];
732 chunk->data [0] = ji;
733 mono_memory_write_barrier ();
734 chunk->num_elements = ++num_elements;
736 /* Shift the elements up one by one. */
737 for (i = num_elements - 2; i >= pos; --i) {
738 mono_memory_write_barrier ();
739 chunk->data [i + 1] = chunk->data [i];
742 /* Now we have room and can insert the new item. */
743 mono_memory_write_barrier ();
744 chunk->data [pos] = ji;
746 /* Set the high code end address chunk entry. */
747 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
748 + chunk->data [chunk->num_elements - 1]->code_size;
750 /* Debugging code, should be removed. */
751 //jit_info_table_check (table);
753 mono_domain_unlock (domain);
757 mono_jit_info_make_tombstone (MonoJitInfo *ji)
759 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
761 tombstone->code_start = ji->code_start;
762 tombstone->code_size = ji->code_size;
763 tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
769 * LOCKING: domain lock
772 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
774 if (domain->num_jit_info_tables <= 1) {
775 /* Can it actually happen that we only have one table
776 but ji is still hazardous? */
777 mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
779 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
784 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
786 MonoJitInfoTable *table;
787 MonoJitInfoTableChunk *chunk;
788 gpointer start = ji->code_start;
791 mono_domain_lock (domain);
792 table = domain->jit_info_table;
794 ++mono_stats.jit_info_table_remove_count;
796 chunk_pos = jit_info_table_index (table, start);
797 g_assert (chunk_pos < table->num_chunks);
799 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
802 chunk = table->chunks [chunk_pos];
804 while (pos < chunk->num_elements) {
805 if (chunk->data [pos] == ji)
808 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
809 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
810 <= (guint8*)ji->code_start + ji->code_size);
817 } while (chunk_pos < table->num_chunks);
820 g_assert (chunk->data [pos] == ji);
822 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
824 /* Debugging code, should be removed. */
825 //jit_info_table_check (table);
827 mono_jit_info_free_or_queue (domain, ji);
829 mono_domain_unlock (domain);
832 static MonoAotModuleInfoTable*
833 mono_aot_module_info_table_new (void)
835 return g_array_new (FALSE, FALSE, sizeof (gpointer));
839 aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
841 int left = 0, right = table->len;
843 while (left < right) {
844 int pos = (left + right) / 2;
845 AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
846 char *start = ainfo->start;
847 char *end = ainfo->end;
851 else if (addr >= end)
861 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
863 AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
866 ainfo->image = image;
867 ainfo->start = start;
870 mono_appdomains_lock ();
873 aot_modules = mono_aot_module_info_table_new ();
875 pos = aot_info_table_index (aot_modules, start);
877 g_array_insert_val (aot_modules, pos, ainfo);
879 mono_appdomains_unlock ();
883 mono_jit_info_find_aot_module (guint8* addr)
885 guint left = 0, right;
890 mono_appdomains_lock ();
892 right = aot_modules->len;
893 while (left < right) {
894 guint pos = (left + right) / 2;
895 AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
897 if (addr < (guint8*)ai->start)
899 else if (addr >= (guint8*)ai->end)
902 mono_appdomains_unlock ();
907 mono_appdomains_unlock ();
913 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
915 jit_info_find_in_aot_func = func;
919 mono_jit_info_get_code_start (MonoJitInfo* ji)
921 return ji->code_start;
925 mono_jit_info_get_code_size (MonoJitInfo* ji)
927 return ji->code_size;
931 mono_jit_info_get_method (MonoJitInfo* ji)
937 jit_info_key_extract (gpointer value)
939 MonoJitInfo *info = (MonoJitInfo*)value;
945 jit_info_next_value (gpointer value)
947 MonoJitInfo *info = (MonoJitInfo*)value;
949 return (gpointer*)&info->next_jit_code_hash;
953 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
955 mono_internal_hash_table_init (jit_code_hash,
956 mono_aligned_addr_hash,
957 jit_info_key_extract,
958 jit_info_next_value);
962 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
964 if (ji->has_generic_jit_info)
965 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
971 * mono_jit_info_get_generic_sharing_context:
974 * Returns the jit info's generic sharing context, or NULL if it
977 MonoGenericSharingContext*
978 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
980 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
983 return gi->generic_sharing_context;
989 * mono_jit_info_set_generic_sharing_context:
991 * @gsctx: a generic sharing context
993 * Sets the jit info's generic sharing context. The jit info must
994 * have memory allocated for the context.
997 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
999 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
1003 gi->generic_sharing_context = gsctx;
1006 MonoTryBlockHoleTableJitInfo*
1007 mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
1009 if (ji->has_try_block_holes) {
1010 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1011 if (ji->has_generic_jit_info)
1012 ptr += sizeof (MonoGenericJitInfo);
1013 return (MonoTryBlockHoleTableJitInfo*)ptr;
1020 mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
1022 if (ji->has_arch_eh_info) {
1023 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1024 if (ji->has_generic_jit_info)
1025 ptr += sizeof (MonoGenericJitInfo);
1026 if (ji->has_try_block_holes)
1027 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
1028 return (MonoArchEHJitInfo*)ptr;
1035 mono_jit_info_get_cas_info (MonoJitInfo *ji)
1037 if (ji->has_cas_info) {
1038 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1039 if (ji->has_generic_jit_info)
1040 ptr += sizeof (MonoGenericJitInfo);
1041 if (ji->has_try_block_holes)
1042 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
1043 if (ji->has_arch_eh_info)
1044 ptr += sizeof (MonoArchEHJitInfo);
1045 return (MonoMethodCasInfo*)ptr;
1052 mono_install_create_domain_hook (MonoCreateDomainFunc func)
1054 create_domain_hook = func;
1058 mono_install_free_domain_hook (MonoFreeDomainFunc func)
1060 free_domain_hook = func;
1064 * mono_string_equal:
1065 * @s1: First string to compare
1066 * @s2: Second string to compare
1068 * Returns FALSE if the strings differ.
1071 mono_string_equal (MonoString *s1, MonoString *s2)
1073 int l1 = mono_string_length (s1);
1074 int l2 = mono_string_length (s2);
1081 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
1086 * @s: the string to hash
1088 * Returns the hash for the string.
1091 mono_string_hash (MonoString *s)
1093 const guint16 *p = mono_string_chars (s);
1094 int i, len = mono_string_length (s);
1097 for (i = 0; i < len; i++) {
1098 h = (h << 5) - h + *p;
1106 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1108 int len = GPOINTER_TO_INT (s1 [0]);
1109 if (len != GPOINTER_TO_INT (s2 [0]))
1112 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1116 mono_ptrarray_hash (gpointer *s)
1119 int len = GPOINTER_TO_INT (s [0]);
1122 for (i = 1; i < len; i++)
1123 hash += GPOINTER_TO_UINT (s [i]);
1129 * Allocate an id for domain and set domain->domain_id.
1130 * LOCKING: must be called while holding appdomains_mutex.
1131 * We try to assign low numbers to the domain, so it can be used
1132 * as an index in data tables to lookup domain-specific info
1133 * with minimal memory overhead. We also try not to reuse the
1134 * same id too quickly (to help debugging).
1137 domain_id_alloc (MonoDomain *domain)
1140 if (!appdomains_list) {
1141 appdomain_list_size = 2;
1142 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1144 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1145 if (!appdomains_list [i]) {
1151 for (i = 0; i < appdomain_next; ++i) {
1152 if (!appdomains_list [i]) {
1159 MonoDomain **new_list;
1160 int new_size = appdomain_list_size * 2;
1161 if (new_size >= (1 << 16))
1162 g_assert_not_reached ();
1163 id = appdomain_list_size;
1164 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1165 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1166 mono_gc_free_fixed (appdomains_list);
1167 appdomains_list = new_list;
1168 appdomain_list_size = new_size;
1170 domain->domain_id = id;
1171 appdomains_list [id] = domain;
1173 if (appdomain_next > appdomain_list_size)
1178 static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1179 static gpointer domain_gc_desc = NULL;
1180 static guint32 domain_shadow_serial = 0L;
1183 mono_domain_create (void)
1186 guint32 shadow_serial;
1188 mono_appdomains_lock ();
1189 shadow_serial = domain_shadow_serial++;
1191 if (!domain_gc_desc) {
1192 unsigned int i, bit = 0;
1193 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1194 bit = i / sizeof (gpointer);
1195 domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32);
1197 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1199 mono_appdomains_unlock ();
1201 #ifdef HAVE_BOEHM_GC
1203 * Boehm doesn't like roots inside GC allocated objects, and alloc_fixed returns
1204 * a GC_MALLOC-ed object, contrary to the api docs. This causes random crashes when
1205 * running the corlib test suite.
1206 * To solve this, we pass a NULL descriptor, and don't register roots.
1208 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL);
1210 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1211 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);
1213 domain->shadow_serial = shadow_serial;
1214 domain->domain = NULL;
1215 domain->setup = NULL;
1216 domain->friendly_name = NULL;
1217 domain->search_path = NULL;
1219 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1221 domain->mp = mono_mempool_new ();
1222 domain->code_mp = mono_code_manager_new ();
1223 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1224 domain->domain_assemblies = NULL;
1225 domain->assembly_bindings = NULL;
1226 domain->assembly_bindings_parsed = FALSE;
1227 domain->class_vtable_array = g_ptr_array_new ();
1228 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1229 domain->static_data_array = NULL;
1230 mono_jit_code_hash_init (&domain->jit_code_hash);
1231 domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1232 domain->num_jit_info_tables = 1;
1233 domain->jit_info_table = jit_info_table_new (domain);
1234 domain->jit_info_free_queue = NULL;
1235 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1236 domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1238 InitializeCriticalSection (&domain->lock);
1239 InitializeCriticalSection (&domain->assemblies_lock);
1240 InitializeCriticalSection (&domain->jit_code_hash_lock);
1241 InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
1243 domain->method_rgctx_hash = NULL;
1245 mono_appdomains_lock ();
1246 domain_id_alloc (domain);
1247 mono_appdomains_unlock ();
1249 #ifndef DISABLE_PERFCOUNTERS
1250 mono_perfcounters->loader_appdomains++;
1251 mono_perfcounters->loader_total_appdomains++;
1254 mono_debug_domain_create (domain);
1256 if (create_domain_hook)
1257 create_domain_hook (domain);
1259 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1265 * mono_init_internal:
1267 * Creates the initial application domain and initializes the mono_defaults
1269 * This function is guaranteed to not run any IL code.
1270 * If exe_filename is not NULL, the method will determine the required runtime
1271 * from the exe configuration file or the version PE field.
1272 * If runtime_version is not NULL, that runtime version will be used.
1273 * Either exe_filename or runtime_version must be provided.
1275 * Returns: the initial domain.
1278 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1280 static MonoDomain *domain = NULL;
1281 MonoAssembly *ass = NULL;
1282 MonoImageOpenStatus status = MONO_IMAGE_OK;
1283 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1287 g_assert_not_reached ();
1290 /* Avoid system error message boxes. */
1291 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1298 #ifndef DISABLE_PERFCOUNTERS
1299 mono_perfcounters_init ();
1302 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1303 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1304 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1306 mono_gc_base_init ();
1308 MONO_FAST_TLS_INIT (tls_appdomain);
1309 mono_native_tls_alloc (&appdomain_thread_id, NULL);
1311 InitializeCriticalSection (&appdomains_mutex);
1313 mono_metadata_init ();
1314 mono_images_init ();
1315 mono_assemblies_init ();
1316 mono_classes_init ();
1317 mono_loader_init ();
1318 mono_reflection_init ();
1319 mono_runtime_init_tls ();
1321 /* FIXME: When should we release this memory? */
1322 MONO_GC_REGISTER_ROOT_FIXED (appdomains_list);
1324 domain = mono_domain_create ();
1325 mono_root_domain = domain;
1327 SET_APPDOMAIN (domain);
1329 /* Get a list of runtimes supported by the exe */
1330 if (exe_filename != NULL) {
1332 * This function will load the exe file as a MonoImage. We need to close it, but
1333 * that would mean it would be reloaded later. So instead, we save it to
1334 * exe_image, and close it during shutdown.
1336 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1339 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1341 exe_image = mono_image_open (exe_filename, NULL);
1343 mono_fixup_exe_image (exe_image);
1345 } else if (runtime_version != NULL) {
1346 runtimes [0] = get_runtime_by_version (runtime_version);
1347 runtimes [1] = NULL;
1350 if (runtimes [0] == NULL) {
1351 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1352 runtimes [0] = default_runtime;
1353 runtimes [1] = NULL;
1354 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1355 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1358 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1359 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1360 current_runtime = runtimes [n];
1361 ass = mono_assembly_load_corlib (current_runtime, &status);
1362 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1367 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1369 case MONO_IMAGE_ERROR_ERRNO: {
1370 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1371 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1372 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1373 g_free (corlib_file);
1376 case MONO_IMAGE_IMAGE_INVALID:
1377 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1378 mono_assembly_getrootdir ());
1380 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1381 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1382 mono_assembly_getrootdir ());
1385 /* to suppress compiler warning */
1391 mono_defaults.corlib = mono_assembly_get_image (ass);
1393 mono_defaults.object_class = mono_class_from_name (
1394 mono_defaults.corlib, "System", "Object");
1395 g_assert (mono_defaults.object_class != 0);
1397 mono_defaults.void_class = mono_class_from_name (
1398 mono_defaults.corlib, "System", "Void");
1399 g_assert (mono_defaults.void_class != 0);
1401 mono_defaults.boolean_class = mono_class_from_name (
1402 mono_defaults.corlib, "System", "Boolean");
1403 g_assert (mono_defaults.boolean_class != 0);
1405 mono_defaults.byte_class = mono_class_from_name (
1406 mono_defaults.corlib, "System", "Byte");
1407 g_assert (mono_defaults.byte_class != 0);
1409 mono_defaults.sbyte_class = mono_class_from_name (
1410 mono_defaults.corlib, "System", "SByte");
1411 g_assert (mono_defaults.sbyte_class != 0);
1413 mono_defaults.int16_class = mono_class_from_name (
1414 mono_defaults.corlib, "System", "Int16");
1415 g_assert (mono_defaults.int16_class != 0);
1417 mono_defaults.uint16_class = mono_class_from_name (
1418 mono_defaults.corlib, "System", "UInt16");
1419 g_assert (mono_defaults.uint16_class != 0);
1421 mono_defaults.int32_class = mono_class_from_name (
1422 mono_defaults.corlib, "System", "Int32");
1423 g_assert (mono_defaults.int32_class != 0);
1425 mono_defaults.uint32_class = mono_class_from_name (
1426 mono_defaults.corlib, "System", "UInt32");
1427 g_assert (mono_defaults.uint32_class != 0);
1429 mono_defaults.uint_class = mono_class_from_name (
1430 mono_defaults.corlib, "System", "UIntPtr");
1431 g_assert (mono_defaults.uint_class != 0);
1433 mono_defaults.int_class = mono_class_from_name (
1434 mono_defaults.corlib, "System", "IntPtr");
1435 g_assert (mono_defaults.int_class != 0);
1437 mono_defaults.int64_class = mono_class_from_name (
1438 mono_defaults.corlib, "System", "Int64");
1439 g_assert (mono_defaults.int64_class != 0);
1441 mono_defaults.uint64_class = mono_class_from_name (
1442 mono_defaults.corlib, "System", "UInt64");
1443 g_assert (mono_defaults.uint64_class != 0);
1445 mono_defaults.single_class = mono_class_from_name (
1446 mono_defaults.corlib, "System", "Single");
1447 g_assert (mono_defaults.single_class != 0);
1449 mono_defaults.double_class = mono_class_from_name (
1450 mono_defaults.corlib, "System", "Double");
1451 g_assert (mono_defaults.double_class != 0);
1453 mono_defaults.char_class = mono_class_from_name (
1454 mono_defaults.corlib, "System", "Char");
1455 g_assert (mono_defaults.char_class != 0);
1457 mono_defaults.string_class = mono_class_from_name (
1458 mono_defaults.corlib, "System", "String");
1459 g_assert (mono_defaults.string_class != 0);
1461 mono_defaults.enum_class = mono_class_from_name (
1462 mono_defaults.corlib, "System", "Enum");
1463 g_assert (mono_defaults.enum_class != 0);
1465 mono_defaults.array_class = mono_class_from_name (
1466 mono_defaults.corlib, "System", "Array");
1467 g_assert (mono_defaults.array_class != 0);
1469 mono_defaults.delegate_class = mono_class_from_name (
1470 mono_defaults.corlib, "System", "Delegate");
1471 g_assert (mono_defaults.delegate_class != 0 );
1473 mono_defaults.multicastdelegate_class = mono_class_from_name (
1474 mono_defaults.corlib, "System", "MulticastDelegate");
1475 g_assert (mono_defaults.multicastdelegate_class != 0 );
1477 mono_defaults.asyncresult_class = mono_class_from_name (
1478 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1480 g_assert (mono_defaults.asyncresult_class != 0 );
1482 mono_defaults.manualresetevent_class = mono_class_from_name (
1483 mono_defaults.corlib, "System.Threading", "ManualResetEvent");
1484 g_assert (mono_defaults.manualresetevent_class != 0 );
1486 mono_defaults.typehandle_class = mono_class_from_name (
1487 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1488 g_assert (mono_defaults.typehandle_class != 0);
1490 mono_defaults.methodhandle_class = mono_class_from_name (
1491 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1492 g_assert (mono_defaults.methodhandle_class != 0);
1494 mono_defaults.fieldhandle_class = mono_class_from_name (
1495 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1496 g_assert (mono_defaults.fieldhandle_class != 0);
1498 mono_defaults.systemtype_class = mono_class_from_name (
1499 mono_defaults.corlib, "System", "Type");
1500 g_assert (mono_defaults.systemtype_class != 0);
1502 mono_defaults.monotype_class = mono_class_from_name (
1503 mono_defaults.corlib, "System", "MonoType");
1504 g_assert (mono_defaults.monotype_class != 0);
1506 mono_defaults.exception_class = mono_class_from_name (
1507 mono_defaults.corlib, "System", "Exception");
1508 g_assert (mono_defaults.exception_class != 0);
1510 mono_defaults.threadabortexception_class = mono_class_from_name (
1511 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1512 g_assert (mono_defaults.threadabortexception_class != 0);
1514 mono_defaults.thread_class = mono_class_from_name (
1515 mono_defaults.corlib, "System.Threading", "Thread");
1516 g_assert (mono_defaults.thread_class != 0);
1518 mono_defaults.internal_thread_class = mono_class_from_name (
1519 mono_defaults.corlib, "System.Threading", "InternalThread");
1520 if (!mono_defaults.internal_thread_class) {
1521 /* This can happen with an old mscorlib */
1522 fprintf (stderr, "Corlib too old for this runtime.\n");
1523 fprintf (stderr, "Loaded from: %s\n",
1524 mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown");
1528 mono_defaults.appdomain_class = mono_class_from_name (
1529 mono_defaults.corlib, "System", "AppDomain");
1530 g_assert (mono_defaults.appdomain_class != 0);
1532 #ifndef DISABLE_REMOTING
1533 mono_defaults.transparent_proxy_class = mono_class_from_name (
1534 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1535 g_assert (mono_defaults.transparent_proxy_class != 0);
1537 mono_defaults.real_proxy_class = mono_class_from_name (
1538 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1539 g_assert (mono_defaults.real_proxy_class != 0);
1541 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1542 mono_defaults.corlib, "System", "MarshalByRefObject");
1543 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1545 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1546 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1547 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1550 mono_defaults.mono_method_message_class = mono_class_from_name (
1551 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1552 g_assert (mono_defaults.mono_method_message_class != 0);
1554 mono_defaults.field_info_class = mono_class_from_name (
1555 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1556 g_assert (mono_defaults.field_info_class != 0);
1558 mono_defaults.method_info_class = mono_class_from_name (
1559 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1560 g_assert (mono_defaults.method_info_class != 0);
1562 mono_defaults.stringbuilder_class = mono_class_from_name (
1563 mono_defaults.corlib, "System.Text", "StringBuilder");
1564 g_assert (mono_defaults.stringbuilder_class != 0);
1566 mono_defaults.math_class = mono_class_from_name (
1567 mono_defaults.corlib, "System", "Math");
1568 g_assert (mono_defaults.math_class != 0);
1570 mono_defaults.stack_frame_class = mono_class_from_name (
1571 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1572 g_assert (mono_defaults.stack_frame_class != 0);
1574 mono_defaults.stack_trace_class = mono_class_from_name (
1575 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1576 g_assert (mono_defaults.stack_trace_class != 0);
1578 mono_defaults.marshal_class = mono_class_from_name (
1579 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1580 g_assert (mono_defaults.marshal_class != 0);
1582 mono_defaults.typed_reference_class = mono_class_from_name (
1583 mono_defaults.corlib, "System", "TypedReference");
1584 g_assert (mono_defaults.typed_reference_class != 0);
1586 mono_defaults.argumenthandle_class = mono_class_from_name (
1587 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1588 g_assert (mono_defaults.argumenthandle_class != 0);
1590 mono_defaults.monitor_class = mono_class_from_name (
1591 mono_defaults.corlib, "System.Threading", "Monitor");
1592 g_assert (mono_defaults.monitor_class != 0);
1594 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1595 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1597 mono_defaults.executioncontext_class = mono_class_from_name (
1598 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1600 mono_defaults.internals_visible_class = mono_class_from_name (
1601 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1603 mono_defaults.critical_finalizer_object = mono_class_from_name (
1604 mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
1607 * mscorlib needs a little help, only now it can load its friends list (after we have
1608 * loaded the InternalsVisibleToAttribute), load it now
1610 mono_assembly_load_friends (ass);
1612 mono_defaults.safehandle_class = mono_class_from_name (
1613 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1615 mono_defaults.handleref_class = mono_class_from_name (
1616 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1618 mono_defaults.attribute_class = mono_class_from_name (
1619 mono_defaults.corlib, "System", "Attribute");
1621 mono_defaults.customattribute_data_class = mono_class_from_name (
1622 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1624 /* these are initialized lazily when COM features are used */
1626 mono_class_init (mono_defaults.array_class);
1627 mono_defaults.generic_nullable_class = mono_class_from_name (
1628 mono_defaults.corlib, "System", "Nullable`1");
1629 mono_defaults.generic_ilist_class = mono_class_from_name (
1630 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1631 mono_defaults.generic_ireadonlylist_class = mono_class_from_name (
1632 mono_defaults.corlib, "System.Collections.Generic", "IReadOnlyList`1");
1634 domain->friendly_name = g_path_get_basename (filename);
1636 _mono_debug_init_corlib (domain);
1644 * Creates the initial application domain and initializes the mono_defaults
1646 * This function is guaranteed to not run any IL code.
1647 * The runtime is initialized using the default runtime version.
1649 * Returns: the initial domain.
1652 mono_init (const char *domain_name)
1654 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1658 * mono_init_from_assembly:
1659 * @domain_name: name to give to the initial domain
1660 * @filename: filename to load on startup
1662 * Used by the runtime, users should use mono_jit_init instead.
1664 * Creates the initial application domain and initializes the mono_defaults
1666 * This function is guaranteed to not run any IL code.
1667 * The runtime is initialized using the runtime version required by the
1668 * provided executable. The version is determined by looking at the exe
1669 * configuration file and the version PE field)
1671 * Returns: the initial domain.
1674 mono_init_from_assembly (const char *domain_name, const char *filename)
1676 return mono_init_internal (domain_name, filename, NULL);
1680 * mono_init_version:
1682 * Used by the runtime, users should use mono_jit_init instead.
1684 * Creates the initial application domain and initializes the mono_defaults
1687 * This function is guaranteed to not run any IL code.
1688 * The runtime is initialized using the provided rutime version.
1690 * Returns: the initial domain.
1693 mono_init_version (const char *domain_name, const char *version)
1695 return mono_init_internal (domain_name, NULL, version);
1701 * Cleans up all metadata modules.
1706 mono_close_exe_image ();
1708 mono_defaults.corlib = NULL;
1710 mono_config_cleanup ();
1711 mono_loader_cleanup ();
1712 mono_classes_cleanup ();
1713 mono_assemblies_cleanup ();
1714 mono_images_cleanup ();
1715 mono_debug_cleanup ();
1716 mono_metadata_cleanup ();
1718 mono_native_tls_free (appdomain_thread_id);
1719 DeleteCriticalSection (&appdomains_mutex);
1727 mono_close_exe_image (void)
1730 mono_image_close (exe_image);
1734 * mono_get_root_domain:
1736 * The root AppDomain is the initial domain created by the runtime when it is
1737 * initialized. Programs execute on this AppDomain, but can create new ones
1738 * later. Currently there is no unmanaged API to create new AppDomains, this
1739 * must be done from managed code.
1741 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1744 mono_get_root_domain (void)
1746 return mono_root_domain;
1752 * Returns: the current domain, to obtain the root domain use
1753 * mono_get_root_domain().
1758 return GET_APPDOMAIN ();
1762 mono_domain_unset (void)
1764 SET_APPDOMAIN (NULL);
1768 mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception)
1770 MonoInternalThread *thread;
1772 if (mono_domain_get () == domain)
1775 SET_APPDOMAIN (domain);
1776 SET_APPCONTEXT (domain->default_context);
1778 if (migrate_exception) {
1779 thread = mono_thread_internal_current ();
1780 if (!thread->abort_exc)
1783 g_assert (thread->abort_exc->object.vtable->domain != domain);
1784 MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
1785 g_assert (thread->abort_exc->object.vtable->domain == domain);
1790 * mono_domain_set_internal:
1791 * @domain: the new domain
1793 * Sets the current domain to @domain.
1796 mono_domain_set_internal (MonoDomain *domain)
1798 mono_domain_set_internal_with_options (domain, TRUE);
1802 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1808 * Create a copy of the data to avoid calling the user callback
1809 * inside the lock because that could lead to deadlocks.
1810 * We can do this because this function is not perf. critical.
1812 mono_appdomains_lock ();
1813 size = appdomain_list_size;
1814 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1815 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1816 mono_appdomains_unlock ();
1818 for (i = 0; i < size; ++i) {
1820 func (copy [i], user_data);
1823 mono_gc_free_fixed (copy);
1827 * mono_domain_assembly_open:
1828 * @domain: the application domain
1829 * @name: file name of the assembly
1831 * fixme: maybe we should integrate this with mono_assembly_open ??
1834 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1836 MonoDomain *current;
1840 mono_domain_assemblies_lock (domain);
1841 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1843 if (strcmp (name, ass->aname.name) == 0) {
1844 mono_domain_assemblies_unlock (domain);
1848 mono_domain_assemblies_unlock (domain);
1850 if (domain != mono_domain_get ()) {
1851 current = mono_domain_get ();
1853 mono_domain_set (domain, FALSE);
1854 ass = mono_assembly_open (name, NULL);
1855 mono_domain_set (current, FALSE);
1857 ass = mono_assembly_open (name, NULL);
1864 unregister_vtable_reflection_type (MonoVTable *vtable)
1866 MonoObject *type = vtable->type;
1868 if (type->vtable->klass != mono_defaults.monotype_class)
1869 MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type);
1873 mono_domain_free (MonoDomain *domain, gboolean force)
1875 int code_size, code_alloc;
1879 if ((domain == mono_root_domain) && !force) {
1880 g_warning ("cant unload root domain");
1884 if (mono_dont_free_domains)
1887 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1889 mono_debug_domain_unload (domain);
1891 mono_appdomains_lock ();
1892 appdomains_list [domain->domain_id] = NULL;
1893 mono_appdomains_unlock ();
1895 /* must do this early as it accesses fields and types */
1896 if (domain->special_static_fields) {
1897 mono_alloc_special_static_data_free (domain->special_static_fields);
1898 g_hash_table_destroy (domain->special_static_fields);
1899 domain->special_static_fields = NULL;
1903 * We must destroy all these hash tables here because they
1904 * contain references to managed objects belonging to the
1905 * domain. Once we let the GC clear the domain there must be
1906 * no more such references, or we'll crash if a collection
1909 mono_g_hash_table_destroy (domain->ldstr_table);
1910 domain->ldstr_table = NULL;
1912 mono_g_hash_table_destroy (domain->env);
1915 if (domain->tlsrec_list) {
1916 mono_thread_destroy_domain_tls (domain);
1917 domain->tlsrec_list = NULL;
1920 mono_reflection_cleanup_domain (domain);
1922 if (domain->type_hash) {
1923 mono_g_hash_table_destroy (domain->type_hash);
1924 domain->type_hash = NULL;
1926 if (domain->type_init_exception_hash) {
1927 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1928 domain->type_init_exception_hash = NULL;
1931 if (domain->class_vtable_array) {
1933 for (i = 0; i < domain->class_vtable_array->len; ++i)
1934 unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i));
1937 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1938 MonoAssembly *ass = tmp->data;
1939 mono_assembly_release_gc_roots (ass);
1942 /* Have to zero out reference fields since they will be invalidated by the clear_domain () call below */
1943 for (p = (gpointer*)&domain->MONO_DOMAIN_FIRST_OBJECT; p < (gpointer*)&domain->MONO_DOMAIN_FIRST_GC_TRACKED; ++p)
1946 /* This needs to be done before closing assemblies */
1947 mono_gc_clear_domain (domain);
1949 /* Close dynamic assemblies first, since they have no ref count */
1950 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1951 MonoAssembly *ass = tmp->data;
1952 if (!ass->image || !ass->image->dynamic)
1954 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);
1955 if (!mono_assembly_close_except_image_pools (ass))
1959 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1960 MonoAssembly *ass = tmp->data;
1963 if (!ass->image || ass->image->dynamic)
1965 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);
1966 if (!mono_assembly_close_except_image_pools (ass))
1970 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1971 MonoAssembly *ass = tmp->data;
1973 mono_assembly_close_finish (ass);
1975 g_slist_free (domain->domain_assemblies);
1976 domain->domain_assemblies = NULL;
1979 * Send this after the assemblies have been unloaded and the domain is still in a
1982 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
1984 if (free_domain_hook)
1985 free_domain_hook (domain);
1987 /* FIXME: free delegate_hash_table when it's used */
1988 if (domain->search_path) {
1989 g_strfreev (domain->search_path);
1990 domain->search_path = NULL;
1992 domain->create_proxy_for_type_method = NULL;
1993 domain->private_invoke_method = NULL;
1994 domain->default_context = NULL;
1995 domain->out_of_memory_ex = NULL;
1996 domain->null_reference_ex = NULL;
1997 domain->stack_overflow_ex = NULL;
1998 domain->ephemeron_tombstone = NULL;
1999 domain->entry_assembly = NULL;
2001 g_free (domain->friendly_name);
2002 domain->friendly_name = NULL;
2003 g_ptr_array_free (domain->class_vtable_array, TRUE);
2004 domain->class_vtable_array = NULL;
2005 g_hash_table_destroy (domain->proxy_vtable_hash);
2006 domain->proxy_vtable_hash = NULL;
2007 if (domain->static_data_array) {
2008 mono_gc_free_fixed (domain->static_data_array);
2009 domain->static_data_array = NULL;
2011 mono_internal_hash_table_destroy (&domain->jit_code_hash);
2014 * There might still be jit info tables of this domain which
2015 * are not freed. Since the domain cannot be in use anymore,
2016 * this will free them.
2018 mono_thread_hazardous_try_free_all ();
2019 g_assert (domain->num_jit_info_tables == 1);
2020 jit_info_table_free (domain->jit_info_table);
2021 domain->jit_info_table = NULL;
2022 g_assert (!domain->jit_info_free_queue);
2024 /* collect statistics */
2025 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
2026 total_domain_code_alloc += code_alloc;
2027 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
2028 max_domain_code_size = MAX (max_domain_code_size, code_size);
2030 #ifdef DEBUG_DOMAIN_UNLOAD
2031 mono_mempool_invalidate (domain->mp);
2032 mono_code_manager_invalidate (domain->code_mp);
2034 #ifndef DISABLE_PERFCOUNTERS
2035 mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
2037 mono_mempool_destroy (domain->mp);
2039 mono_code_manager_destroy (domain->code_mp);
2040 domain->code_mp = NULL;
2043 g_hash_table_destroy (domain->finalizable_objects_hash);
2044 domain->finalizable_objects_hash = NULL;
2045 if (domain->method_rgctx_hash) {
2046 g_hash_table_destroy (domain->method_rgctx_hash);
2047 domain->method_rgctx_hash = NULL;
2049 if (domain->generic_virtual_cases) {
2050 g_hash_table_destroy (domain->generic_virtual_cases);
2051 domain->generic_virtual_cases = NULL;
2053 if (domain->generic_virtual_thunks) {
2054 g_hash_table_destroy (domain->generic_virtual_thunks);
2055 domain->generic_virtual_thunks = NULL;
2057 if (domain->ftnptrs_hash) {
2058 g_hash_table_destroy (domain->ftnptrs_hash);
2059 domain->ftnptrs_hash = NULL;
2062 DeleteCriticalSection (&domain->finalizable_objects_hash_lock);
2063 DeleteCriticalSection (&domain->assemblies_lock);
2064 DeleteCriticalSection (&domain->jit_code_hash_lock);
2065 DeleteCriticalSection (&domain->lock);
2066 domain->setup = NULL;
2068 mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
2070 /* FIXME: anything else required ? */
2072 mono_gc_free_fixed (domain);
2074 #ifndef DISABLE_PERFCOUNTERS
2075 mono_perfcounters->loader_appdomains--;
2078 if (domain == mono_root_domain)
2079 mono_root_domain = NULL;
2083 * mono_domain_get_id:
2086 * Returns: the a domain for a specific domain id.
2089 mono_domain_get_by_id (gint32 domainid)
2091 MonoDomain * domain;
2093 mono_appdomains_lock ();
2094 if (domainid < appdomain_list_size)
2095 domain = appdomains_list [domainid];
2098 mono_appdomains_unlock ();
2104 mono_domain_get_id (MonoDomain *domain)
2106 return domain->domain_id;
2110 * mono_domain_alloc:
2112 * LOCKING: Acquires the domain lock.
2115 mono_domain_alloc (MonoDomain *domain, guint size)
2119 mono_domain_lock (domain);
2120 #ifndef DISABLE_PERFCOUNTERS
2121 mono_perfcounters->loader_bytes += size;
2123 res = mono_mempool_alloc (domain->mp, size);
2124 mono_domain_unlock (domain);
2130 * mono_domain_alloc0:
2132 * LOCKING: Acquires the domain lock.
2135 mono_domain_alloc0 (MonoDomain *domain, guint size)
2139 mono_domain_lock (domain);
2140 #ifndef DISABLE_PERFCOUNTERS
2141 mono_perfcounters->loader_bytes += size;
2143 res = mono_mempool_alloc0 (domain->mp, size);
2144 mono_domain_unlock (domain);
2150 * mono_domain_code_reserve:
2152 * LOCKING: Acquires the domain lock.
2155 mono_domain_code_reserve (MonoDomain *domain, int size)
2159 mono_domain_lock (domain);
2160 res = mono_code_manager_reserve (domain->code_mp, size);
2161 mono_domain_unlock (domain);
2167 * mono_domain_code_reserve_align:
2169 * LOCKING: Acquires the domain lock.
2172 mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment)
2176 mono_domain_lock (domain);
2177 res = mono_code_manager_reserve_align (domain->code_mp, size, alignment);
2178 mono_domain_unlock (domain);
2184 * mono_domain_code_commit:
2186 * LOCKING: Acquires the domain lock.
2189 mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize)
2191 mono_domain_lock (domain);
2192 mono_code_manager_commit (domain->code_mp, data, size, newsize);
2193 mono_domain_unlock (domain);
2196 #if defined(__native_client_codegen__) && defined(__native_client__)
2198 * Given the temporary buffer (allocated by mono_domain_code_reserve) into which
2199 * we are generating code, return a pointer to the destination in the dynamic
2200 * code segment into which the code will be copied when mono_domain_code_commit
2202 * LOCKING: Acquires the domain lock.
2205 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2208 mono_domain_lock (domain);
2209 dest = nacl_code_manager_get_code_dest (domain->code_mp, data);
2210 mono_domain_unlock (domain);
2215 * Convenience function which calls mono_domain_code_commit to validate and copy
2216 * the code. The caller sets *buf_base and *buf_size to the start and size of
2217 * the buffer (allocated by mono_domain_code_reserve), and *code_end to the byte
2218 * after the last instruction byte. On return, *buf_base will point to the start
2219 * of the copied in the code segment, and *code_end will point after the end of
2223 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2225 guint8 *tmp = nacl_domain_get_code_dest (domain, *buf_base);
2226 mono_domain_code_commit (domain, *buf_base, buf_size, *code_end - *buf_base);
2227 *code_end = tmp + (*code_end - *buf_base);
2233 /* no-op versions of Native Client functions */
2236 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2242 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2249 * mono_domain_code_foreach:
2250 * Iterate over the code thunks of the code manager of @domain.
2252 * The @func callback MUST not take any locks. If it really needs to, it must respect
2253 * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety
2254 * LOCKING: Acquires the domain lock.
2258 mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data)
2260 mono_domain_lock (domain);
2261 mono_code_manager_foreach (domain->code_mp, func, user_data);
2262 mono_domain_unlock (domain);
2267 mono_context_set (MonoAppContext * new_context)
2269 SET_APPCONTEXT (new_context);
2273 mono_context_get (void)
2275 return GET_APPCONTEXT ();
2278 /* LOCKING: the caller holds the lock for this domain */
2280 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
2282 /* The first entry in the array is the index of the next free slot
2283 * and the total size of the array
2286 if (domain->static_data_array) {
2287 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
2288 next = GPOINTER_TO_INT (domain->static_data_array [0]);
2290 /* 'data' is allocated by alloc_fixed */
2291 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2));
2292 mono_gc_memmove (new_array, domain->static_data_array, sizeof (gpointer) * size);
2294 new_array [1] = GINT_TO_POINTER (size);
2295 mono_gc_free_fixed (domain->static_data_array);
2296 domain->static_data_array = new_array;
2300 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, MONO_GC_ROOT_DESCR_FOR_FIXED (size));
2302 new_array [0] = GINT_TO_POINTER (next);
2303 new_array [1] = GINT_TO_POINTER (size);
2304 domain->static_data_array = new_array;
2306 domain->static_data_array [next++] = data;
2307 domain->static_data_array [0] = GINT_TO_POINTER (next);
2311 mono_get_corlib (void)
2313 return mono_defaults.corlib;
2317 mono_get_object_class (void)
2319 return mono_defaults.object_class;
2323 mono_get_byte_class (void)
2325 return mono_defaults.byte_class;
2329 mono_get_void_class (void)
2331 return mono_defaults.void_class;
2335 mono_get_boolean_class (void)
2337 return mono_defaults.boolean_class;
2341 mono_get_sbyte_class (void)
2343 return mono_defaults.sbyte_class;
2347 mono_get_int16_class (void)
2349 return mono_defaults.int16_class;
2353 mono_get_uint16_class (void)
2355 return mono_defaults.uint16_class;
2359 mono_get_int32_class (void)
2361 return mono_defaults.int32_class;
2365 mono_get_uint32_class (void)
2367 return mono_defaults.uint32_class;
2371 mono_get_intptr_class (void)
2373 return mono_defaults.int_class;
2377 mono_get_uintptr_class (void)
2379 return mono_defaults.uint_class;
2383 mono_get_int64_class (void)
2385 return mono_defaults.int64_class;
2389 mono_get_uint64_class (void)
2391 return mono_defaults.uint64_class;
2395 mono_get_single_class (void)
2397 return mono_defaults.single_class;
2401 mono_get_double_class (void)
2403 return mono_defaults.double_class;
2407 mono_get_char_class (void)
2409 return mono_defaults.char_class;
2413 mono_get_string_class (void)
2415 return mono_defaults.string_class;
2419 mono_get_enum_class (void)
2421 return mono_defaults.enum_class;
2425 mono_get_array_class (void)
2427 return mono_defaults.array_class;
2431 mono_get_thread_class (void)
2433 return mono_defaults.thread_class;
2437 mono_get_exception_class (void)
2439 return mono_defaults.exception_class;
2443 static char* get_attribute_value (const gchar **attribute_names,
2444 const gchar **attribute_values,
2445 const char *att_name)
2448 for (n=0; attribute_names[n] != NULL; n++) {
2449 if (strcmp (attribute_names[n], att_name) == 0)
2450 return g_strdup (attribute_values[n]);
2455 static void start_element (GMarkupParseContext *context,
2456 const gchar *element_name,
2457 const gchar **attribute_names,
2458 const gchar **attribute_values,
2462 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2464 if (strcmp (element_name, "configuration") == 0) {
2465 app_config->configuration_count++;
2468 if (strcmp (element_name, "startup") == 0) {
2469 app_config->startup_count++;
2473 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2476 if (strcmp (element_name, "requiredRuntime") == 0) {
2477 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2478 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2479 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2480 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2484 static void end_element (GMarkupParseContext *context,
2485 const gchar *element_name,
2489 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2491 if (strcmp (element_name, "configuration") == 0) {
2492 app_config->configuration_count--;
2493 } else if (strcmp (element_name, "startup") == 0) {
2494 app_config->startup_count--;
2498 static const GMarkupParser
2507 static AppConfigInfo *
2508 app_config_parse (const char *exe_filename)
2510 AppConfigInfo *app_config;
2511 GMarkupParseContext *context;
2514 const char *bundled_config;
2515 char *config_filename;
2517 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2519 if (bundled_config) {
2520 text = g_strdup (bundled_config);
2521 len = strlen (text);
2523 config_filename = g_strconcat (exe_filename, ".config", NULL);
2525 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2526 g_free (config_filename);
2529 g_free (config_filename);
2532 app_config = g_new0 (AppConfigInfo, 1);
2534 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2535 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2536 g_markup_parse_context_end_parse (context, NULL);
2538 g_markup_parse_context_free (context);
2544 app_config_free (AppConfigInfo* app_config)
2547 GSList *list = app_config->supported_runtimes;
2548 while (list != NULL) {
2549 rt = (char*)list->data;
2551 list = g_slist_next (list);
2553 g_slist_free (app_config->supported_runtimes);
2554 g_free (app_config->required_runtime);
2555 g_free (app_config);
2559 static const MonoRuntimeInfo*
2560 get_runtime_by_version (const char *version)
2563 int max = G_N_ELEMENTS (supported_runtimes);
2569 for (n=0; n<max; n++) {
2570 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2571 return &supported_runtimes[n];
2574 vlen = strlen (version);
2575 if (vlen >= 4 && version [1] - '0' >= 4) {
2576 for (n=0; n<max; n++) {
2577 if (strncmp (version, supported_runtimes[n].runtime_version, 4) == 0)
2578 return &supported_runtimes[n];
2586 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2588 AppConfigInfo* app_config;
2590 const MonoRuntimeInfo* runtime = NULL;
2591 MonoImage *image = NULL;
2593 app_config = app_config_parse (exe_file);
2595 if (app_config != NULL) {
2596 /* Check supportedRuntime elements, if none is supported, fail.
2597 * If there are no such elements, look for a requiredRuntime element.
2599 if (app_config->supported_runtimes != NULL) {
2601 GSList *list = app_config->supported_runtimes;
2602 while (list != NULL) {
2603 version = (char*) list->data;
2604 runtime = get_runtime_by_version (version);
2605 if (runtime != NULL)
2606 runtimes [n++] = runtime;
2607 list = g_slist_next (list);
2609 runtimes [n] = NULL;
2610 app_config_free (app_config);
2614 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2615 if (app_config->required_runtime != NULL) {
2616 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2617 runtimes [1] = NULL;
2618 app_config_free (app_config);
2621 app_config_free (app_config);
2624 /* Look for a runtime with the exact version */
2625 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2628 image = mono_image_open (exe_file, NULL);
2630 if (image == NULL) {
2631 /* The image is wrong or the file was not found. In this case return
2632 * a default runtime and leave to the initialization method the work of
2633 * reporting the error.
2635 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2636 runtimes [1] = NULL;
2642 runtimes [0] = get_runtime_by_version (image->version);
2643 runtimes [1] = NULL;
2648 * mono_get_runtime_info:
2650 * Returns: the version of the current runtime instance.
2652 const MonoRuntimeInfo*
2653 mono_get_runtime_info (void)
2655 return current_runtime;
2659 mono_debugger_check_runtime_version (const char *filename)
2661 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2662 const MonoRuntimeInfo *rinfo;
2665 get_runtimes_from_exe (filename, &image, runtimes);
2666 rinfo = runtimes [0];
2669 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2671 if (rinfo != current_runtime)
2672 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2673 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2674 filename, rinfo->runtime_version);
2680 * mono_framework_version:
2682 * Return the major version of the framework curently executing.
2685 mono_framework_version (void)
2687 return current_runtime->framework_version [0] - '0';