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/atomic.h>
21 #include <mono/utils/mono-compiler.h>
22 #include <mono/utils/mono-logger-internal.h>
23 #include <mono/utils/mono-membar.h>
24 #include <mono/utils/mono-counters.h>
25 #include <mono/utils/hazard-pointer.h>
26 #include <mono/utils/mono-tls.h>
27 #include <mono/utils/mono-mmap.h>
28 #include <mono/utils/mono-threads.h>
29 #include <mono/metadata/object.h>
30 #include <mono/metadata/object-internals.h>
31 #include <mono/metadata/domain-internals.h>
32 #include <mono/metadata/class-internals.h>
33 #include <mono/metadata/assembly.h>
34 #include <mono/metadata/exception.h>
35 #include <mono/metadata/metadata-internals.h>
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/appdomain.h>
38 #include <mono/metadata/mono-debug-debugger.h>
39 #include <mono/metadata/mono-config.h>
40 #include <mono/metadata/threads-types.h>
41 #include <mono/metadata/runtime.h>
42 #include <metadata/threads.h>
43 #include <metadata/profiler-private.h>
44 #include <mono/metadata/coree.h>
46 #define DEBUG_DOMAIN_UNLOAD 1
48 /* we need to use both the Tls* functions and __thread because
49 * some archs may generate faster jit code with one meachanism
50 * or the other (we used to do it because tls slots were GC-tracked,
51 * but we can't depend on this).
53 static MonoNativeTlsKey appdomain_thread_id;
55 #ifdef MONO_HAVE_FAST_TLS
57 MONO_FAST_TLS_DECLARE(tls_appdomain);
59 #define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain))
61 #define SET_APPDOMAIN(x) do { \
62 MonoThreadInfo *info; \
63 MONO_FAST_TLS_SET (tls_appdomain,x); \
64 mono_native_tls_set_value (appdomain_thread_id, x); \
65 mono_gc_set_current_thread_appdomain (x); \
66 info = mono_thread_info_current (); \
68 mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x)); \
71 #else /* !MONO_HAVE_FAST_TLS */
73 #define GET_APPDOMAIN() ((MonoDomain *)mono_native_tls_get_value (appdomain_thread_id))
74 #define SET_APPDOMAIN(x) do { \
75 MonoThreadInfo *info; \
76 mono_native_tls_set_value (appdomain_thread_id, x); \
77 mono_gc_set_current_thread_appdomain (x); \
78 info = mono_thread_info_current (); \
80 mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x)); \
85 #define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext)
86 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x))
88 static guint16 appdomain_list_size = 0;
89 static guint16 appdomain_next = 0;
90 static MonoDomain **appdomains_list = NULL;
91 static MonoImage *exe_image;
93 gboolean mono_dont_free_domains;
95 #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
96 #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
97 static CRITICAL_SECTION appdomains_mutex;
99 static MonoDomain *mono_root_domain = NULL;
101 /* some statistics */
102 static int max_domain_code_size = 0;
103 static int max_domain_code_alloc = 0;
104 static int total_domain_code_alloc = 0;
106 /* AppConfigInfo: Information about runtime versions supported by an
110 GSList *supported_runtimes;
111 char *required_runtime;
112 int configuration_count;
116 static const MonoRuntimeInfo *current_runtime = NULL;
118 static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
120 /* This is the list of runtime versions supported by this JIT.
122 static const MonoRuntimeInfo supported_runtimes[] = {
123 {"v2.0.50215","2.0", { {2,0,0,0}, { 8,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
124 {"v2.0.50727","2.0", { {2,0,0,0}, { 8,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
125 {"v4.0.30319","4.5", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
126 {"v4.0.30128","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
127 {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
128 {"moonlight", "2.1", { {2,0,5,0}, { 9,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
132 /* The stable runtime version */
133 #define DEFAULT_RUNTIME_VERSION "v2.0.50727"
135 /* Callbacks installed by the JIT */
136 static MonoCreateDomainFunc create_domain_hook;
137 static MonoFreeDomainFunc free_domain_hook;
139 /* This is intentionally not in the header file, so people don't misuse it. */
140 extern void _mono_debug_init_corlib (MonoDomain *domain);
143 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
145 static const MonoRuntimeInfo*
146 get_runtime_by_version (const char *version);
149 mono_domain_get_tls_key (void)
151 return appdomain_thread_id;
155 mono_domain_get_tls_offset (void)
158 MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
159 /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
164 #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
165 #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
166 #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)
168 #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
169 #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
171 #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
172 #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->d.method == JIT_INFO_TOMBSTONE_MARKER)
174 #define JIT_INFO_TABLE_HAZARD_INDEX 0
175 #define JIT_INFO_HAZARD_INDEX 1
178 jit_info_table_num_elements (MonoJitInfoTable *table)
181 int num_elements = 0;
183 for (i = 0; i < table->num_chunks; ++i) {
184 MonoJitInfoTableChunk *chunk = table->chunks [i];
185 int chunk_num_elements = chunk->num_elements;
188 for (j = 0; j < chunk_num_elements; ++j) {
189 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
197 static MonoJitInfoTableChunk*
198 jit_info_table_new_chunk (void)
200 MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
206 static MonoJitInfoTable *
207 jit_info_table_new (MonoDomain *domain)
209 MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
211 table->domain = domain;
212 table->num_chunks = 1;
213 table->chunks [0] = jit_info_table_new_chunk ();
219 jit_info_table_free (MonoJitInfoTable *table)
222 int num_chunks = table->num_chunks;
223 MonoDomain *domain = table->domain;
225 mono_domain_lock (domain);
227 table->domain->num_jit_info_tables--;
228 if (table->domain->num_jit_info_tables <= 1) {
231 for (list = table->domain->jit_info_free_queue; list; list = list->next)
234 g_slist_free (table->domain->jit_info_free_queue);
235 table->domain->jit_info_free_queue = NULL;
238 /* At this point we assume that there are no other threads
239 still accessing the table, so we don't have to worry about
240 hazardous pointers. */
242 for (i = 0; i < num_chunks; ++i) {
243 MonoJitInfoTableChunk *chunk = table->chunks [i];
247 if (--chunk->refcount > 0)
250 num_elements = chunk->num_elements;
251 for (j = 0; j < num_elements; ++j) {
252 MonoJitInfo *ji = chunk->data [j];
254 if (IS_JIT_INFO_TOMBSTONE (ji))
261 mono_domain_unlock (domain);
266 /* The jit_info_table is sorted in ascending order by the end
267 * addresses of the compiled methods. The reason why we have to do
268 * this is that once we introduce tombstones, it becomes possible for
269 * code ranges to overlap, and if we sort by code start and insert at
270 * the back of the table, we cannot guarantee that we won't overlook
273 * There are actually two possible ways to do the sorting and
274 * inserting which work with our lock-free mechanism:
276 * 1. Sort by start address and insert at the front. When looking for
277 * an entry, find the last one with a start address lower than the one
278 * you're looking for, then work your way to the front of the table.
280 * 2. Sort by end address and insert at the back. When looking for an
281 * entry, find the first one with an end address higher than the one
282 * you're looking for, then work your way to the end of the table.
284 * We chose the latter out of convenience.
287 jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
289 int left = 0, right = table->num_chunks;
291 g_assert (left < right);
294 int pos = (left + right) / 2;
295 MonoJitInfoTableChunk *chunk = table->chunks [pos];
297 if (addr < chunk->last_code_end)
301 } while (left < right);
302 g_assert (left == right);
304 if (left >= table->num_chunks)
305 return table->num_chunks - 1;
310 jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
312 int left = 0, right = chunk->num_elements;
314 while (left < right) {
315 int pos = (left + right) / 2;
316 MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
317 gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
324 g_assert (left == right);
330 jit_info_table_find (MonoJitInfoTable *table, MonoThreadHazardPointers *hp, gint8 *addr)
335 chunk_pos = jit_info_table_index (table, (gint8*)addr);
336 g_assert (chunk_pos < table->num_chunks);
338 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
340 /* We now have a position that's very close to that of the
341 first element whose end address is higher than the one
342 we're looking for. If we don't have the exact position,
343 then we have a position below that one, so we'll just
344 search upward until we find our element. */
346 MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
348 while (pos < chunk->num_elements) {
349 ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
353 if (IS_JIT_INFO_TOMBSTONE (ji)) {
354 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
357 if ((gint8*)addr >= (gint8*)ji->code_start
358 && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
359 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
363 /* If we find a non-tombstone element which is already
364 beyond what we're looking for, we have to end the
366 if ((gint8*)addr < (gint8*)ji->code_start)
372 } while (chunk_pos < table->num_chunks);
376 mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
381 * mono_jit_info_table_find_internal:
383 * If TRY_AOT is FALSE, avoid loading information for missing methods from AOT images, which is currently not async safe.
384 * In this case, only those AOT methods will be found whose jit info is already loaded.
385 * ASYNC SAFETY: When called in an async context (mono_thread_info_is_async_context ()), this is async safe.
386 * In this case, the returned MonoJitInfo might not have metadata information, in particular,
387 * mono_jit_info_get_method () could fail.
390 mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot)
392 MonoJitInfoTable *table;
393 MonoJitInfo *ji, *module_ji;
394 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
396 ++mono_stats.jit_info_table_lookup_count;
398 /* First we have to get the domain's jit_info_table. This is
399 complicated by the fact that a writer might substitute a
400 new table and free the old one. What the writer guarantees
401 us is that it looks at the hazard pointers after it has
402 changed the jit_info_table pointer. So, if we guard the
403 table by a hazard pointer and make sure that the pointer is
404 still there after we've made it hazardous, we don't have to
405 worry about the writer freeing the table. */
406 table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
408 ji = jit_info_table_find (table, hp, (gint8*)addr);
410 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
414 /* Maybe its an AOT module */
415 if (try_aot && mono_root_domain && mono_root_domain->aot_modules) {
416 table = get_hazardous_pointer ((gpointer volatile*)&mono_root_domain->aot_modules, hp, JIT_INFO_TABLE_HAZARD_INDEX);
417 module_ji = jit_info_table_find (table, hp, (gint8*)addr);
419 ji = jit_info_find_in_aot_func (domain, module_ji->d.image, addr);
421 mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
428 mono_jit_info_table_find (MonoDomain *domain, char *addr)
430 return mono_jit_info_table_find_internal (domain, addr, TRUE);
433 static G_GNUC_UNUSED void
434 jit_info_table_check (MonoJitInfoTable *table)
438 for (i = 0; i < table->num_chunks; ++i) {
439 MonoJitInfoTableChunk *chunk = table->chunks [i];
442 g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
443 if (chunk->refcount > 10)
444 printf("warning: chunk refcount is %d\n", chunk->refcount);
445 g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
447 for (j = 0; j < chunk->num_elements; ++j) {
448 MonoJitInfo *this = chunk->data [j];
451 g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
453 if (j < chunk->num_elements - 1)
454 next = chunk->data [j + 1];
455 else if (i < table->num_chunks - 1) {
458 for (k = i + 1; k < table->num_chunks; ++k)
459 if (table->chunks [k]->num_elements > 0)
462 if (k >= table->num_chunks)
465 g_assert (table->chunks [k]->num_elements > 0);
466 next = table->chunks [k]->data [0];
470 g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
475 static MonoJitInfoTable*
476 jit_info_table_realloc (MonoJitInfoTable *old)
479 int num_elements = jit_info_table_num_elements (old);
482 int new_chunk, new_element;
483 MonoJitInfoTable *new;
485 /* number of needed places for elements needed */
486 required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
487 num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
488 if (num_chunks == 0) {
489 g_assert (num_elements == 0);
490 return jit_info_table_new (old->domain);
492 g_assert (num_chunks > 0);
494 new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
495 new->domain = old->domain;
496 new->num_chunks = num_chunks;
498 for (i = 0; i < num_chunks; ++i)
499 new->chunks [i] = jit_info_table_new_chunk ();
503 for (i = 0; i < old->num_chunks; ++i) {
504 MonoJitInfoTableChunk *chunk = old->chunks [i];
505 int chunk_num_elements = chunk->num_elements;
508 for (j = 0; j < chunk_num_elements; ++j) {
509 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
510 g_assert (new_chunk < num_chunks);
511 new->chunks [new_chunk]->data [new_element] = chunk->data [j];
512 if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
513 new->chunks [new_chunk]->num_elements = new_element;
521 if (new_chunk < num_chunks) {
522 g_assert (new_chunk == num_chunks - 1);
523 new->chunks [new_chunk]->num_elements = new_element;
524 g_assert (new->chunks [new_chunk]->num_elements > 0);
527 for (i = 0; i < num_chunks; ++i) {
528 MonoJitInfoTableChunk *chunk = new->chunks [i];
529 MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
531 new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
538 jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
540 MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
541 MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
543 g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
545 new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
546 new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
548 memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
549 memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
551 new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
552 + new1->data [new1->num_elements - 1]->code_size;
553 new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
554 + new2->data [new2->num_elements - 1]->code_size;
560 static MonoJitInfoTable*
561 jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
563 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
564 + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
567 new_table->domain = table->domain;
568 new_table->num_chunks = table->num_chunks + 1;
571 for (i = 0; i < table->num_chunks; ++i) {
572 if (table->chunks [i] == chunk) {
573 jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
576 new_table->chunks [j] = table->chunks [i];
577 ++new_table->chunks [j]->refcount;
582 g_assert (j == new_table->num_chunks);
587 static MonoJitInfoTableChunk*
588 jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
590 MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
594 for (i = 0; i < old->num_elements; ++i) {
595 if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
596 new->data [j++] = old->data [i];
599 new->num_elements = j;
600 if (new->num_elements > 0)
601 new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
603 new->last_code_end = old->last_code_end;
608 static MonoJitInfoTable*
609 jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
611 MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
612 + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
615 new_table->domain = table->domain;
616 new_table->num_chunks = table->num_chunks;
619 for (i = 0; i < table->num_chunks; ++i) {
620 if (table->chunks [i] == chunk)
621 new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
623 new_table->chunks [j] = table->chunks [i];
624 ++new_table->chunks [j]->refcount;
629 g_assert (j == new_table->num_chunks);
634 /* As we add an element to the table the case can arise that the chunk
635 * to which we need to add is already full. In that case we have to
636 * allocate a new table and do something about that chunk. We have
637 * several strategies:
639 * If the number of elements in the table is below the low watermark
640 * or above the high watermark, we reallocate the whole table.
641 * Otherwise we only concern ourselves with the overflowing chunk:
643 * If there are no tombstones in the chunk then we split the chunk in
644 * two, each half full.
646 * If the chunk does contain tombstones, we just make a new copy of
647 * the chunk without the tombstones, which will have room for at least
648 * the one element we have to add.
650 static MonoJitInfoTable*
651 jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
653 int num_elements = jit_info_table_num_elements (table);
656 if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
657 || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
658 //printf ("reallocing table\n");
659 return jit_info_table_realloc (table);
662 /* count the number of non-tombstone elements in the chunk */
664 for (i = 0; i < chunk->num_elements; ++i) {
665 if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
669 if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
670 //printf ("splitting chunk\n");
671 return jit_info_table_copy_and_split_chunk (table, chunk);
674 //printf ("purifying chunk\n");
675 return jit_info_table_copy_and_purify_chunk (table, chunk);
678 /* We add elements to the table by first making space for them by
679 * shifting the elements at the back to the right, one at a time.
680 * This results in duplicate entries during the process, but during
681 * all the time the table is in a sorted state. Also, when an element
682 * is replaced by another one, the element that replaces it has an end
683 * address that is equal to or lower than that of the replaced
684 * element. That property is necessary to guarantee that when
685 * searching for an element we end up at a position not higher than
686 * the one we're looking for (i.e. we either find the element directly
687 * or we end up to the left of it).
690 jit_info_table_add (MonoDomain *domain, MonoJitInfoTable *volatile *table_ptr, MonoJitInfo *ji)
692 MonoJitInfoTable *table;
693 MonoJitInfoTableChunk *chunk;
701 chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
702 g_assert (chunk_pos < table->num_chunks);
703 chunk = table->chunks [chunk_pos];
705 if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
706 MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
708 /* Debugging code, should be removed. */
709 //jit_info_table_check (new_table);
711 *table_ptr = new_table;
712 mono_memory_barrier ();
713 domain->num_jit_info_tables++;
714 mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free, TRUE, FALSE);
720 /* Debugging code, should be removed. */
721 //jit_info_table_check (table);
723 num_elements = chunk->num_elements;
725 pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
727 /* First we need to size up the chunk by one, by copying the
728 last item, or inserting the first one, if the table is
730 if (num_elements > 0)
731 chunk->data [num_elements] = chunk->data [num_elements - 1];
733 chunk->data [0] = ji;
734 mono_memory_write_barrier ();
735 chunk->num_elements = ++num_elements;
737 /* Shift the elements up one by one. */
738 for (i = num_elements - 2; i >= pos; --i) {
739 mono_memory_write_barrier ();
740 chunk->data [i + 1] = chunk->data [i];
743 /* Now we have room and can insert the new item. */
744 mono_memory_write_barrier ();
745 chunk->data [pos] = ji;
747 /* Set the high code end address chunk entry. */
748 chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
749 + chunk->data [chunk->num_elements - 1]->code_size;
751 /* Debugging code, should be removed. */
752 //jit_info_table_check (table);
756 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
758 g_assert (ji->d.method != NULL);
760 mono_domain_lock (domain);
762 ++mono_stats.jit_info_table_insert_count;
764 jit_info_table_add (domain, &domain->jit_info_table, ji);
766 mono_domain_unlock (domain);
770 mono_jit_info_make_tombstone (MonoJitInfo *ji)
772 MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
774 tombstone->code_start = ji->code_start;
775 tombstone->code_size = ji->code_size;
776 tombstone->d.method = JIT_INFO_TOMBSTONE_MARKER;
782 * LOCKING: domain lock
785 mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
787 if (domain->num_jit_info_tables <= 1) {
788 /* Can it actually happen that we only have one table
789 but ji is still hazardous? */
790 mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
792 domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
797 jit_info_table_remove (MonoJitInfoTable *table, MonoJitInfo *ji)
799 MonoJitInfoTableChunk *chunk;
800 gpointer start = ji->code_start;
803 chunk_pos = jit_info_table_index (table, start);
804 g_assert (chunk_pos < table->num_chunks);
806 pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
809 chunk = table->chunks [chunk_pos];
811 while (pos < chunk->num_elements) {
812 if (chunk->data [pos] == ji)
815 g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
816 g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
817 <= (guint8*)ji->code_start + ji->code_size);
824 } while (chunk_pos < table->num_chunks);
827 g_assert (chunk->data [pos] == ji);
829 chunk->data [pos] = mono_jit_info_make_tombstone (ji);
831 /* Debugging code, should be removed. */
832 //jit_info_table_check (table);
836 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
838 MonoJitInfoTable *table;
840 mono_domain_lock (domain);
841 table = domain->jit_info_table;
843 ++mono_stats.jit_info_table_remove_count;
845 jit_info_table_remove (table, ji);
847 mono_jit_info_free_or_queue (domain, ji);
849 mono_domain_unlock (domain);
853 mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
857 mono_appdomains_lock ();
860 * We reuse MonoJitInfoTable to store AOT module info,
861 * this gives us async-safe lookup.
863 g_assert (mono_root_domain);
864 if (!mono_root_domain->aot_modules) {
865 mono_root_domain->num_jit_info_tables ++;
866 mono_root_domain->aot_modules = jit_info_table_new (mono_root_domain);
869 ji = g_new0 (MonoJitInfo, 1);
871 ji->code_start = start;
872 ji->code_size = (guint8*)end - (guint8*)start;
873 jit_info_table_add (mono_root_domain, &mono_root_domain->aot_modules, ji);
875 mono_appdomains_unlock ();
879 mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
881 jit_info_find_in_aot_func = func;
885 mono_jit_info_get_code_start (MonoJitInfo* ji)
887 return ji->code_start;
891 mono_jit_info_get_code_size (MonoJitInfo* ji)
893 return ji->code_size;
897 mono_jit_info_get_method (MonoJitInfo* ji)
899 g_assert (!ji->async);
904 jit_info_key_extract (gpointer value)
906 MonoJitInfo *info = (MonoJitInfo*)value;
908 return info->d.method;
912 jit_info_next_value (gpointer value)
914 MonoJitInfo *info = (MonoJitInfo*)value;
916 return (gpointer*)&info->next_jit_code_hash;
920 mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
922 mono_internal_hash_table_init (jit_code_hash,
923 mono_aligned_addr_hash,
924 jit_info_key_extract,
925 jit_info_next_value);
929 mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
931 if (ji->has_generic_jit_info)
932 return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
938 * mono_jit_info_get_generic_sharing_context:
941 * Returns the jit info's generic sharing context, or NULL if it
944 MonoGenericSharingContext*
945 mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
947 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
950 return gi->generic_sharing_context;
956 * mono_jit_info_set_generic_sharing_context:
958 * @gsctx: a generic sharing context
960 * Sets the jit info's generic sharing context. The jit info must
961 * have memory allocated for the context.
964 mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
966 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
970 gi->generic_sharing_context = gsctx;
973 MonoTryBlockHoleTableJitInfo*
974 mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
976 if (ji->has_try_block_holes) {
977 char *ptr = (char*)&ji->clauses [ji->num_clauses];
978 if (ji->has_generic_jit_info)
979 ptr += sizeof (MonoGenericJitInfo);
980 return (MonoTryBlockHoleTableJitInfo*)ptr;
987 mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
989 if (ji->has_arch_eh_info) {
990 char *ptr = (char*)&ji->clauses [ji->num_clauses];
991 if (ji->has_generic_jit_info)
992 ptr += sizeof (MonoGenericJitInfo);
993 if (ji->has_try_block_holes)
994 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
995 return (MonoArchEHJitInfo*)ptr;
1002 mono_jit_info_get_cas_info (MonoJitInfo *ji)
1004 if (ji->has_cas_info) {
1005 char *ptr = (char*)&ji->clauses [ji->num_clauses];
1006 if (ji->has_generic_jit_info)
1007 ptr += sizeof (MonoGenericJitInfo);
1008 if (ji->has_try_block_holes)
1009 ptr += sizeof (MonoTryBlockHoleTableJitInfo);
1010 if (ji->has_arch_eh_info)
1011 ptr += sizeof (MonoArchEHJitInfo);
1012 return (MonoMethodCasInfo*)ptr;
1018 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
1019 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
1021 static LockFreeMempool*
1022 lock_free_mempool_new (void)
1024 return g_new0 (LockFreeMempool, 1);
1028 lock_free_mempool_free (LockFreeMempool *mp)
1030 LockFreeMempoolChunk *chunk, *next;
1035 mono_vfree (chunk, mono_pagesize ());
1041 * This is async safe
1043 static LockFreeMempoolChunk*
1044 lock_free_mempool_chunk_new (LockFreeMempool *mp, int len)
1046 LockFreeMempoolChunk *chunk, *prev;
1049 size = mono_pagesize ();
1050 while (size - sizeof (LockFreeMempoolChunk) < len)
1051 size += mono_pagesize ();
1052 chunk = mono_valloc (0, size, MONO_MMAP_READ|MONO_MMAP_WRITE);
1054 chunk->mem = ALIGN_PTR_TO ((char*)chunk + sizeof (LockFreeMempoolChunk), 16);
1055 chunk->size = ((char*)chunk + size) - (char*)chunk->mem;
1058 /* Add to list of chunks lock-free */
1061 if (InterlockedCompareExchangePointer ((volatile gpointer*)&mp->chunks, chunk, prev) == prev)
1070 * This is async safe
1073 lock_free_mempool_alloc0 (LockFreeMempool *mp, guint size)
1075 LockFreeMempoolChunk *chunk;
1079 // FIXME: Free the allocator
1081 size = ALIGN_TO (size, 8);
1082 chunk = mp->current;
1084 chunk = lock_free_mempool_chunk_new (mp, size);
1085 mono_memory_barrier ();
1087 mp->current = chunk;
1090 /* The code below is lock-free, 'chunk' is shared state */
1091 oldpos = InterlockedExchangeAdd (&chunk->pos, size);
1092 if (oldpos + size > chunk->size) {
1093 chunk = lock_free_mempool_chunk_new (mp, size);
1094 g_assert (chunk->pos + size <= chunk->size);
1097 mono_memory_barrier ();
1098 mp->current = chunk;
1100 res = (char*)chunk->mem + oldpos;
1107 mono_install_create_domain_hook (MonoCreateDomainFunc func)
1109 create_domain_hook = func;
1113 mono_install_free_domain_hook (MonoFreeDomainFunc func)
1115 free_domain_hook = func;
1119 * mono_string_equal:
1120 * @s1: First string to compare
1121 * @s2: Second string to compare
1123 * Returns FALSE if the strings differ.
1126 mono_string_equal (MonoString *s1, MonoString *s2)
1128 int l1 = mono_string_length (s1);
1129 int l2 = mono_string_length (s2);
1136 return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
1141 * @s: the string to hash
1143 * Returns the hash for the string.
1146 mono_string_hash (MonoString *s)
1148 const guint16 *p = mono_string_chars (s);
1149 int i, len = mono_string_length (s);
1152 for (i = 0; i < len; i++) {
1153 h = (h << 5) - h + *p;
1161 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
1163 int len = GPOINTER_TO_INT (s1 [0]);
1164 if (len != GPOINTER_TO_INT (s2 [0]))
1167 return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
1171 mono_ptrarray_hash (gpointer *s)
1174 int len = GPOINTER_TO_INT (s [0]);
1177 for (i = 1; i < len; i++)
1178 hash += GPOINTER_TO_UINT (s [i]);
1184 * Allocate an id for domain and set domain->domain_id.
1185 * LOCKING: must be called while holding appdomains_mutex.
1186 * We try to assign low numbers to the domain, so it can be used
1187 * as an index in data tables to lookup domain-specific info
1188 * with minimal memory overhead. We also try not to reuse the
1189 * same id too quickly (to help debugging).
1192 domain_id_alloc (MonoDomain *domain)
1195 if (!appdomains_list) {
1196 appdomain_list_size = 2;
1197 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1199 for (i = appdomain_next; i < appdomain_list_size; ++i) {
1200 if (!appdomains_list [i]) {
1206 for (i = 0; i < appdomain_next; ++i) {
1207 if (!appdomains_list [i]) {
1214 MonoDomain **new_list;
1215 int new_size = appdomain_list_size * 2;
1216 if (new_size >= (1 << 16))
1217 g_assert_not_reached ();
1218 id = appdomain_list_size;
1219 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
1220 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
1221 mono_gc_free_fixed (appdomains_list);
1222 appdomains_list = new_list;
1223 appdomain_list_size = new_size;
1225 domain->domain_id = id;
1226 appdomains_list [id] = domain;
1228 if (appdomain_next > appdomain_list_size)
1233 static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
1234 static gpointer domain_gc_desc = NULL;
1235 static guint32 domain_shadow_serial = 0L;
1238 mono_domain_create (void)
1241 guint32 shadow_serial;
1243 mono_appdomains_lock ();
1244 shadow_serial = domain_shadow_serial++;
1246 if (!domain_gc_desc) {
1247 unsigned int i, bit = 0;
1248 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
1249 bit = i / sizeof (gpointer);
1250 domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32);
1252 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
1254 mono_appdomains_unlock ();
1256 #ifdef HAVE_BOEHM_GC
1258 * Boehm doesn't like roots inside GC allocated objects, and alloc_fixed returns
1259 * a GC_MALLOC-ed object, contrary to the api docs. This causes random crashes when
1260 * running the corlib test suite.
1261 * To solve this, we pass a NULL descriptor, and don't register roots.
1263 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL);
1265 domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
1266 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);
1268 domain->shadow_serial = shadow_serial;
1269 domain->domain = NULL;
1270 domain->setup = NULL;
1271 domain->friendly_name = NULL;
1272 domain->search_path = NULL;
1274 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
1276 domain->mp = mono_mempool_new ();
1277 domain->code_mp = mono_code_manager_new ();
1278 domain->lock_free_mp = lock_free_mempool_new ();
1279 domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1280 domain->domain_assemblies = NULL;
1281 domain->assembly_bindings = NULL;
1282 domain->assembly_bindings_parsed = FALSE;
1283 domain->class_vtable_array = g_ptr_array_new ();
1284 domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
1285 domain->static_data_array = NULL;
1286 mono_jit_code_hash_init (&domain->jit_code_hash);
1287 domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
1288 domain->num_jit_info_tables = 1;
1289 domain->jit_info_table = jit_info_table_new (domain);
1290 domain->jit_info_free_queue = NULL;
1291 domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1292 domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
1294 InitializeCriticalSection (&domain->lock);
1295 InitializeCriticalSection (&domain->assemblies_lock);
1296 InitializeCriticalSection (&domain->jit_code_hash_lock);
1297 InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
1299 domain->method_rgctx_hash = NULL;
1301 mono_appdomains_lock ();
1302 domain_id_alloc (domain);
1303 mono_appdomains_unlock ();
1305 #ifndef DISABLE_PERFCOUNTERS
1306 mono_perfcounters->loader_appdomains++;
1307 mono_perfcounters->loader_total_appdomains++;
1310 mono_debug_domain_create (domain);
1312 if (create_domain_hook)
1313 create_domain_hook (domain);
1315 mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
1321 * mono_init_internal:
1323 * Creates the initial application domain and initializes the mono_defaults
1325 * This function is guaranteed to not run any IL code.
1326 * If exe_filename is not NULL, the method will determine the required runtime
1327 * from the exe configuration file or the version PE field.
1328 * If runtime_version is not NULL, that runtime version will be used.
1329 * Either exe_filename or runtime_version must be provided.
1331 * Returns: the initial domain.
1334 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
1336 static MonoDomain *domain = NULL;
1337 MonoAssembly *ass = NULL;
1338 MonoImageOpenStatus status = MONO_IMAGE_OK;
1339 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1343 g_assert_not_reached ();
1346 /* Avoid system error message boxes. */
1347 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1354 #ifndef DISABLE_PERFCOUNTERS
1355 mono_perfcounters_init ();
1358 mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
1359 mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
1360 mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
1362 mono_gc_base_init ();
1364 MONO_FAST_TLS_INIT (tls_appdomain);
1365 mono_native_tls_alloc (&appdomain_thread_id, NULL);
1367 InitializeCriticalSection (&appdomains_mutex);
1369 mono_metadata_init ();
1370 mono_images_init ();
1371 mono_assemblies_init ();
1372 mono_classes_init ();
1373 mono_loader_init ();
1374 mono_reflection_init ();
1375 mono_runtime_init_tls ();
1377 /* FIXME: When should we release this memory? */
1378 MONO_GC_REGISTER_ROOT_FIXED (appdomains_list);
1380 domain = mono_domain_create ();
1381 mono_root_domain = domain;
1383 SET_APPDOMAIN (domain);
1385 /* Get a list of runtimes supported by the exe */
1386 if (exe_filename != NULL) {
1388 * This function will load the exe file as a MonoImage. We need to close it, but
1389 * that would mean it would be reloaded later. So instead, we save it to
1390 * exe_image, and close it during shutdown.
1392 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
1395 exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
1397 exe_image = mono_image_open (exe_filename, NULL);
1399 mono_fixup_exe_image (exe_image);
1401 } else if (runtime_version != NULL) {
1402 runtimes [0] = get_runtime_by_version (runtime_version);
1403 runtimes [1] = NULL;
1406 if (runtimes [0] == NULL) {
1407 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1408 runtimes [0] = default_runtime;
1409 runtimes [1] = NULL;
1410 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
1411 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
1414 /* The selected runtime will be the first one for which there is a mscrolib.dll */
1415 for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
1416 current_runtime = runtimes [n];
1417 ass = mono_assembly_load_corlib (current_runtime, &status);
1418 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
1423 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
1425 case MONO_IMAGE_ERROR_ERRNO: {
1426 char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
1427 g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
1428 g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
1429 g_free (corlib_file);
1432 case MONO_IMAGE_IMAGE_INVALID:
1433 g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
1434 mono_assembly_getrootdir ());
1436 case MONO_IMAGE_MISSING_ASSEMBLYREF:
1437 g_print ("Missing assembly reference in %s/mscorlib.dll\n",
1438 mono_assembly_getrootdir ());
1441 /* to suppress compiler warning */
1447 mono_defaults.corlib = mono_assembly_get_image (ass);
1449 mono_defaults.object_class = mono_class_from_name (
1450 mono_defaults.corlib, "System", "Object");
1451 g_assert (mono_defaults.object_class != 0);
1453 mono_defaults.void_class = mono_class_from_name (
1454 mono_defaults.corlib, "System", "Void");
1455 g_assert (mono_defaults.void_class != 0);
1457 mono_defaults.boolean_class = mono_class_from_name (
1458 mono_defaults.corlib, "System", "Boolean");
1459 g_assert (mono_defaults.boolean_class != 0);
1461 mono_defaults.byte_class = mono_class_from_name (
1462 mono_defaults.corlib, "System", "Byte");
1463 g_assert (mono_defaults.byte_class != 0);
1465 mono_defaults.sbyte_class = mono_class_from_name (
1466 mono_defaults.corlib, "System", "SByte");
1467 g_assert (mono_defaults.sbyte_class != 0);
1469 mono_defaults.int16_class = mono_class_from_name (
1470 mono_defaults.corlib, "System", "Int16");
1471 g_assert (mono_defaults.int16_class != 0);
1473 mono_defaults.uint16_class = mono_class_from_name (
1474 mono_defaults.corlib, "System", "UInt16");
1475 g_assert (mono_defaults.uint16_class != 0);
1477 mono_defaults.int32_class = mono_class_from_name (
1478 mono_defaults.corlib, "System", "Int32");
1479 g_assert (mono_defaults.int32_class != 0);
1481 mono_defaults.uint32_class = mono_class_from_name (
1482 mono_defaults.corlib, "System", "UInt32");
1483 g_assert (mono_defaults.uint32_class != 0);
1485 mono_defaults.uint_class = mono_class_from_name (
1486 mono_defaults.corlib, "System", "UIntPtr");
1487 g_assert (mono_defaults.uint_class != 0);
1489 mono_defaults.int_class = mono_class_from_name (
1490 mono_defaults.corlib, "System", "IntPtr");
1491 g_assert (mono_defaults.int_class != 0);
1493 mono_defaults.int64_class = mono_class_from_name (
1494 mono_defaults.corlib, "System", "Int64");
1495 g_assert (mono_defaults.int64_class != 0);
1497 mono_defaults.uint64_class = mono_class_from_name (
1498 mono_defaults.corlib, "System", "UInt64");
1499 g_assert (mono_defaults.uint64_class != 0);
1501 mono_defaults.single_class = mono_class_from_name (
1502 mono_defaults.corlib, "System", "Single");
1503 g_assert (mono_defaults.single_class != 0);
1505 mono_defaults.double_class = mono_class_from_name (
1506 mono_defaults.corlib, "System", "Double");
1507 g_assert (mono_defaults.double_class != 0);
1509 mono_defaults.char_class = mono_class_from_name (
1510 mono_defaults.corlib, "System", "Char");
1511 g_assert (mono_defaults.char_class != 0);
1513 mono_defaults.string_class = mono_class_from_name (
1514 mono_defaults.corlib, "System", "String");
1515 g_assert (mono_defaults.string_class != 0);
1517 mono_defaults.enum_class = mono_class_from_name (
1518 mono_defaults.corlib, "System", "Enum");
1519 g_assert (mono_defaults.enum_class != 0);
1521 mono_defaults.array_class = mono_class_from_name (
1522 mono_defaults.corlib, "System", "Array");
1523 g_assert (mono_defaults.array_class != 0);
1525 mono_defaults.delegate_class = mono_class_from_name (
1526 mono_defaults.corlib, "System", "Delegate");
1527 g_assert (mono_defaults.delegate_class != 0 );
1529 mono_defaults.multicastdelegate_class = mono_class_from_name (
1530 mono_defaults.corlib, "System", "MulticastDelegate");
1531 g_assert (mono_defaults.multicastdelegate_class != 0 );
1533 mono_defaults.asyncresult_class = mono_class_from_name (
1534 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
1536 g_assert (mono_defaults.asyncresult_class != 0 );
1538 mono_defaults.manualresetevent_class = mono_class_from_name (
1539 mono_defaults.corlib, "System.Threading", "ManualResetEvent");
1540 g_assert (mono_defaults.manualresetevent_class != 0 );
1542 mono_defaults.typehandle_class = mono_class_from_name (
1543 mono_defaults.corlib, "System", "RuntimeTypeHandle");
1544 g_assert (mono_defaults.typehandle_class != 0);
1546 mono_defaults.methodhandle_class = mono_class_from_name (
1547 mono_defaults.corlib, "System", "RuntimeMethodHandle");
1548 g_assert (mono_defaults.methodhandle_class != 0);
1550 mono_defaults.fieldhandle_class = mono_class_from_name (
1551 mono_defaults.corlib, "System", "RuntimeFieldHandle");
1552 g_assert (mono_defaults.fieldhandle_class != 0);
1554 mono_defaults.systemtype_class = mono_class_from_name (
1555 mono_defaults.corlib, "System", "Type");
1556 g_assert (mono_defaults.systemtype_class != 0);
1558 mono_defaults.monotype_class = mono_class_from_name (
1559 mono_defaults.corlib, "System", "MonoType");
1560 g_assert (mono_defaults.monotype_class != 0);
1562 mono_defaults.exception_class = mono_class_from_name (
1563 mono_defaults.corlib, "System", "Exception");
1564 g_assert (mono_defaults.exception_class != 0);
1566 mono_defaults.threadabortexception_class = mono_class_from_name (
1567 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
1568 g_assert (mono_defaults.threadabortexception_class != 0);
1570 mono_defaults.thread_class = mono_class_from_name (
1571 mono_defaults.corlib, "System.Threading", "Thread");
1572 g_assert (mono_defaults.thread_class != 0);
1574 mono_defaults.internal_thread_class = mono_class_from_name (
1575 mono_defaults.corlib, "System.Threading", "InternalThread");
1576 if (!mono_defaults.internal_thread_class) {
1577 /* This can happen with an old mscorlib */
1578 fprintf (stderr, "Corlib too old for this runtime.\n");
1579 fprintf (stderr, "Loaded from: %s\n",
1580 mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown");
1584 mono_defaults.appdomain_class = mono_class_from_name (
1585 mono_defaults.corlib, "System", "AppDomain");
1586 g_assert (mono_defaults.appdomain_class != 0);
1588 #ifndef DISABLE_REMOTING
1589 mono_defaults.transparent_proxy_class = mono_class_from_name (
1590 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
1591 g_assert (mono_defaults.transparent_proxy_class != 0);
1593 mono_defaults.real_proxy_class = mono_class_from_name (
1594 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
1595 g_assert (mono_defaults.real_proxy_class != 0);
1597 mono_defaults.marshalbyrefobject_class = mono_class_from_name (
1598 mono_defaults.corlib, "System", "MarshalByRefObject");
1599 g_assert (mono_defaults.marshalbyrefobject_class != 0);
1601 mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
1602 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
1603 g_assert (mono_defaults.iremotingtypeinfo_class != 0);
1606 mono_defaults.mono_method_message_class = mono_class_from_name (
1607 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
1608 g_assert (mono_defaults.mono_method_message_class != 0);
1610 mono_defaults.field_info_class = mono_class_from_name (
1611 mono_defaults.corlib, "System.Reflection", "FieldInfo");
1612 g_assert (mono_defaults.field_info_class != 0);
1614 mono_defaults.method_info_class = mono_class_from_name (
1615 mono_defaults.corlib, "System.Reflection", "MethodInfo");
1616 g_assert (mono_defaults.method_info_class != 0);
1618 mono_defaults.stringbuilder_class = mono_class_from_name (
1619 mono_defaults.corlib, "System.Text", "StringBuilder");
1620 g_assert (mono_defaults.stringbuilder_class != 0);
1622 mono_defaults.math_class = mono_class_from_name (
1623 mono_defaults.corlib, "System", "Math");
1624 g_assert (mono_defaults.math_class != 0);
1626 mono_defaults.stack_frame_class = mono_class_from_name (
1627 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
1628 g_assert (mono_defaults.stack_frame_class != 0);
1630 mono_defaults.stack_trace_class = mono_class_from_name (
1631 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
1632 g_assert (mono_defaults.stack_trace_class != 0);
1634 mono_defaults.marshal_class = mono_class_from_name (
1635 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
1636 g_assert (mono_defaults.marshal_class != 0);
1638 mono_defaults.typed_reference_class = mono_class_from_name (
1639 mono_defaults.corlib, "System", "TypedReference");
1640 g_assert (mono_defaults.typed_reference_class != 0);
1642 mono_defaults.argumenthandle_class = mono_class_from_name (
1643 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
1644 g_assert (mono_defaults.argumenthandle_class != 0);
1646 mono_defaults.monitor_class = mono_class_from_name (
1647 mono_defaults.corlib, "System.Threading", "Monitor");
1648 g_assert (mono_defaults.monitor_class != 0);
1650 mono_defaults.runtimesecurityframe_class = mono_class_from_name (
1651 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
1653 mono_defaults.executioncontext_class = mono_class_from_name (
1654 mono_defaults.corlib, "System.Threading", "ExecutionContext");
1656 mono_defaults.internals_visible_class = mono_class_from_name (
1657 mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1659 mono_defaults.critical_finalizer_object = mono_class_from_name (
1660 mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
1663 * mscorlib needs a little help, only now it can load its friends list (after we have
1664 * loaded the InternalsVisibleToAttribute), load it now
1666 mono_assembly_load_friends (ass);
1668 mono_defaults.safehandle_class = mono_class_from_name (
1669 mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
1671 mono_defaults.handleref_class = mono_class_from_name (
1672 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
1674 mono_defaults.attribute_class = mono_class_from_name (
1675 mono_defaults.corlib, "System", "Attribute");
1677 mono_defaults.customattribute_data_class = mono_class_from_name (
1678 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
1680 /* these are initialized lazily when COM features are used */
1682 mono_class_init (mono_defaults.array_class);
1683 mono_defaults.generic_nullable_class = mono_class_from_name (
1684 mono_defaults.corlib, "System", "Nullable`1");
1685 mono_defaults.generic_ilist_class = mono_class_from_name (
1686 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
1687 mono_defaults.generic_ireadonlylist_class = mono_class_from_name (
1688 mono_defaults.corlib, "System.Collections.Generic", "IReadOnlyList`1");
1690 domain->friendly_name = g_path_get_basename (filename);
1692 _mono_debug_init_corlib (domain);
1700 * Creates the initial application domain and initializes the mono_defaults
1702 * This function is guaranteed to not run any IL code.
1703 * The runtime is initialized using the default runtime version.
1705 * Returns: the initial domain.
1708 mono_init (const char *domain_name)
1710 return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
1714 * mono_init_from_assembly:
1715 * @domain_name: name to give to the initial domain
1716 * @filename: filename to load on startup
1718 * Used by the runtime, users should use mono_jit_init instead.
1720 * Creates the initial application domain and initializes the mono_defaults
1722 * This function is guaranteed to not run any IL code.
1723 * The runtime is initialized using the runtime version required by the
1724 * provided executable. The version is determined by looking at the exe
1725 * configuration file and the version PE field)
1727 * Returns: the initial domain.
1730 mono_init_from_assembly (const char *domain_name, const char *filename)
1732 return mono_init_internal (domain_name, filename, NULL);
1736 * mono_init_version:
1738 * Used by the runtime, users should use mono_jit_init instead.
1740 * Creates the initial application domain and initializes the mono_defaults
1743 * This function is guaranteed to not run any IL code.
1744 * The runtime is initialized using the provided rutime version.
1746 * Returns: the initial domain.
1749 mono_init_version (const char *domain_name, const char *version)
1751 return mono_init_internal (domain_name, NULL, version);
1757 * Cleans up all metadata modules.
1762 mono_close_exe_image ();
1764 mono_defaults.corlib = NULL;
1766 mono_config_cleanup ();
1767 mono_loader_cleanup ();
1768 mono_classes_cleanup ();
1769 mono_assemblies_cleanup ();
1770 mono_images_cleanup ();
1771 mono_debug_cleanup ();
1772 mono_metadata_cleanup ();
1774 mono_native_tls_free (appdomain_thread_id);
1775 DeleteCriticalSection (&appdomains_mutex);
1783 mono_close_exe_image (void)
1786 mono_image_close (exe_image);
1790 * mono_get_root_domain:
1792 * The root AppDomain is the initial domain created by the runtime when it is
1793 * initialized. Programs execute on this AppDomain, but can create new ones
1794 * later. Currently there is no unmanaged API to create new AppDomains, this
1795 * must be done from managed code.
1797 * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
1800 mono_get_root_domain (void)
1802 return mono_root_domain;
1808 * Returns: the current domain, to obtain the root domain use
1809 * mono_get_root_domain().
1814 return GET_APPDOMAIN ();
1818 mono_domain_unset (void)
1820 SET_APPDOMAIN (NULL);
1824 mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception)
1826 MonoInternalThread *thread;
1828 if (mono_domain_get () == domain)
1831 SET_APPDOMAIN (domain);
1832 SET_APPCONTEXT (domain->default_context);
1834 if (migrate_exception) {
1835 thread = mono_thread_internal_current ();
1836 if (!thread->abort_exc)
1839 g_assert (thread->abort_exc->object.vtable->domain != domain);
1840 MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
1841 g_assert (thread->abort_exc->object.vtable->domain == domain);
1846 * mono_domain_set_internal:
1847 * @domain: the new domain
1849 * Sets the current domain to @domain.
1852 mono_domain_set_internal (MonoDomain *domain)
1854 mono_domain_set_internal_with_options (domain, TRUE);
1858 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
1864 * Create a copy of the data to avoid calling the user callback
1865 * inside the lock because that could lead to deadlocks.
1866 * We can do this because this function is not perf. critical.
1868 mono_appdomains_lock ();
1869 size = appdomain_list_size;
1870 copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
1871 memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
1872 mono_appdomains_unlock ();
1874 for (i = 0; i < size; ++i) {
1876 func (copy [i], user_data);
1879 mono_gc_free_fixed (copy);
1883 * mono_domain_assembly_open:
1884 * @domain: the application domain
1885 * @name: file name of the assembly
1887 * fixme: maybe we should integrate this with mono_assembly_open ??
1890 mono_domain_assembly_open (MonoDomain *domain, const char *name)
1892 MonoDomain *current;
1896 mono_domain_assemblies_lock (domain);
1897 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1899 if (strcmp (name, ass->aname.name) == 0) {
1900 mono_domain_assemblies_unlock (domain);
1904 mono_domain_assemblies_unlock (domain);
1906 if (domain != mono_domain_get ()) {
1907 current = mono_domain_get ();
1909 mono_domain_set (domain, FALSE);
1910 ass = mono_assembly_open (name, NULL);
1911 mono_domain_set (current, FALSE);
1913 ass = mono_assembly_open (name, NULL);
1920 unregister_vtable_reflection_type (MonoVTable *vtable)
1922 MonoObject *type = vtable->type;
1924 if (type->vtable->klass != mono_defaults.monotype_class)
1925 MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type);
1929 mono_domain_free (MonoDomain *domain, gboolean force)
1931 int code_size, code_alloc;
1935 if ((domain == mono_root_domain) && !force) {
1936 g_warning ("cant unload root domain");
1940 if (mono_dont_free_domains)
1943 mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1945 mono_debug_domain_unload (domain);
1947 mono_appdomains_lock ();
1948 appdomains_list [domain->domain_id] = NULL;
1949 mono_appdomains_unlock ();
1951 /* must do this early as it accesses fields and types */
1952 if (domain->special_static_fields) {
1953 mono_alloc_special_static_data_free (domain->special_static_fields);
1954 g_hash_table_destroy (domain->special_static_fields);
1955 domain->special_static_fields = NULL;
1959 * We must destroy all these hash tables here because they
1960 * contain references to managed objects belonging to the
1961 * domain. Once we let the GC clear the domain there must be
1962 * no more such references, or we'll crash if a collection
1965 mono_g_hash_table_destroy (domain->ldstr_table);
1966 domain->ldstr_table = NULL;
1968 mono_g_hash_table_destroy (domain->env);
1971 if (domain->tlsrec_list) {
1972 mono_thread_destroy_domain_tls (domain);
1973 domain->tlsrec_list = NULL;
1976 mono_reflection_cleanup_domain (domain);
1978 if (domain->type_hash) {
1979 mono_g_hash_table_destroy (domain->type_hash);
1980 domain->type_hash = NULL;
1982 if (domain->type_init_exception_hash) {
1983 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1984 domain->type_init_exception_hash = NULL;
1987 if (domain->class_vtable_array) {
1989 for (i = 0; i < domain->class_vtable_array->len; ++i)
1990 unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i));
1993 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1994 MonoAssembly *ass = tmp->data;
1995 mono_assembly_release_gc_roots (ass);
1998 /* Have to zero out reference fields since they will be invalidated by the clear_domain () call below */
1999 for (p = (gpointer*)&domain->MONO_DOMAIN_FIRST_OBJECT; p < (gpointer*)&domain->MONO_DOMAIN_FIRST_GC_TRACKED; ++p)
2002 /* This needs to be done before closing assemblies */
2003 mono_gc_clear_domain (domain);
2005 /* Close dynamic assemblies first, since they have no ref count */
2006 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
2007 MonoAssembly *ass = tmp->data;
2008 if (!ass->image || !ass->image->dynamic)
2010 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);
2011 if (!mono_assembly_close_except_image_pools (ass))
2015 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
2016 MonoAssembly *ass = tmp->data;
2019 if (!ass->image || ass->image->dynamic)
2021 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);
2022 if (!mono_assembly_close_except_image_pools (ass))
2026 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
2027 MonoAssembly *ass = tmp->data;
2029 mono_assembly_close_finish (ass);
2031 g_slist_free (domain->domain_assemblies);
2032 domain->domain_assemblies = NULL;
2035 * Send this after the assemblies have been unloaded and the domain is still in a
2038 mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
2040 if (free_domain_hook)
2041 free_domain_hook (domain);
2043 /* FIXME: free delegate_hash_table when it's used */
2044 if (domain->search_path) {
2045 g_strfreev (domain->search_path);
2046 domain->search_path = NULL;
2048 domain->create_proxy_for_type_method = NULL;
2049 domain->private_invoke_method = NULL;
2050 domain->default_context = NULL;
2051 domain->out_of_memory_ex = NULL;
2052 domain->null_reference_ex = NULL;
2053 domain->stack_overflow_ex = NULL;
2054 domain->ephemeron_tombstone = NULL;
2055 domain->entry_assembly = NULL;
2057 g_free (domain->friendly_name);
2058 domain->friendly_name = NULL;
2059 g_ptr_array_free (domain->class_vtable_array, TRUE);
2060 domain->class_vtable_array = NULL;
2061 g_hash_table_destroy (domain->proxy_vtable_hash);
2062 domain->proxy_vtable_hash = NULL;
2063 if (domain->static_data_array) {
2064 mono_gc_free_fixed (domain->static_data_array);
2065 domain->static_data_array = NULL;
2067 mono_internal_hash_table_destroy (&domain->jit_code_hash);
2070 * There might still be jit info tables of this domain which
2071 * are not freed. Since the domain cannot be in use anymore,
2072 * this will free them.
2074 mono_thread_hazardous_try_free_all ();
2075 if (domain->aot_modules)
2076 jit_info_table_free (domain->aot_modules);
2077 g_assert (domain->num_jit_info_tables == 1);
2078 jit_info_table_free (domain->jit_info_table);
2079 domain->jit_info_table = NULL;
2080 g_assert (!domain->jit_info_free_queue);
2082 /* collect statistics */
2083 code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
2084 total_domain_code_alloc += code_alloc;
2085 max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
2086 max_domain_code_size = MAX (max_domain_code_size, code_size);
2088 #ifdef DEBUG_DOMAIN_UNLOAD
2089 mono_mempool_invalidate (domain->mp);
2090 mono_code_manager_invalidate (domain->code_mp);
2092 #ifndef DISABLE_PERFCOUNTERS
2093 mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
2095 mono_mempool_destroy (domain->mp);
2097 mono_code_manager_destroy (domain->code_mp);
2098 domain->code_mp = NULL;
2100 lock_free_mempool_free (domain->lock_free_mp);
2101 domain->lock_free_mp = NULL;
2103 g_hash_table_destroy (domain->finalizable_objects_hash);
2104 domain->finalizable_objects_hash = NULL;
2105 if (domain->method_rgctx_hash) {
2106 g_hash_table_destroy (domain->method_rgctx_hash);
2107 domain->method_rgctx_hash = NULL;
2109 if (domain->generic_virtual_cases) {
2110 g_hash_table_destroy (domain->generic_virtual_cases);
2111 domain->generic_virtual_cases = NULL;
2113 if (domain->generic_virtual_thunks) {
2114 g_hash_table_destroy (domain->generic_virtual_thunks);
2115 domain->generic_virtual_thunks = NULL;
2117 if (domain->ftnptrs_hash) {
2118 g_hash_table_destroy (domain->ftnptrs_hash);
2119 domain->ftnptrs_hash = NULL;
2122 DeleteCriticalSection (&domain->finalizable_objects_hash_lock);
2123 DeleteCriticalSection (&domain->assemblies_lock);
2124 DeleteCriticalSection (&domain->jit_code_hash_lock);
2125 DeleteCriticalSection (&domain->lock);
2126 domain->setup = NULL;
2128 mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
2130 /* FIXME: anything else required ? */
2132 mono_gc_free_fixed (domain);
2134 #ifndef DISABLE_PERFCOUNTERS
2135 mono_perfcounters->loader_appdomains--;
2138 if (domain == mono_root_domain)
2139 mono_root_domain = NULL;
2143 * mono_domain_get_id:
2146 * Returns: the a domain for a specific domain id.
2149 mono_domain_get_by_id (gint32 domainid)
2151 MonoDomain * domain;
2153 mono_appdomains_lock ();
2154 if (domainid < appdomain_list_size)
2155 domain = appdomains_list [domainid];
2158 mono_appdomains_unlock ();
2164 mono_domain_get_id (MonoDomain *domain)
2166 return domain->domain_id;
2170 * mono_domain_alloc:
2172 * LOCKING: Acquires the domain lock.
2175 mono_domain_alloc (MonoDomain *domain, guint size)
2179 mono_domain_lock (domain);
2180 #ifndef DISABLE_PERFCOUNTERS
2181 mono_perfcounters->loader_bytes += size;
2183 res = mono_mempool_alloc (domain->mp, size);
2184 mono_domain_unlock (domain);
2190 * mono_domain_alloc0:
2192 * LOCKING: Acquires the domain lock.
2195 mono_domain_alloc0 (MonoDomain *domain, guint size)
2199 mono_domain_lock (domain);
2200 #ifndef DISABLE_PERFCOUNTERS
2201 mono_perfcounters->loader_bytes += size;
2203 res = mono_mempool_alloc0 (domain->mp, size);
2204 mono_domain_unlock (domain);
2210 mono_domain_alloc0_lock_free (MonoDomain *domain, guint size)
2212 return lock_free_mempool_alloc0 (domain->lock_free_mp, size);
2216 * mono_domain_code_reserve:
2218 * LOCKING: Acquires the domain lock.
2221 mono_domain_code_reserve (MonoDomain *domain, int size)
2225 mono_domain_lock (domain);
2226 res = mono_code_manager_reserve (domain->code_mp, size);
2227 mono_domain_unlock (domain);
2233 * mono_domain_code_reserve_align:
2235 * LOCKING: Acquires the domain lock.
2238 mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment)
2242 mono_domain_lock (domain);
2243 res = mono_code_manager_reserve_align (domain->code_mp, size, alignment);
2244 mono_domain_unlock (domain);
2250 * mono_domain_code_commit:
2252 * LOCKING: Acquires the domain lock.
2255 mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize)
2257 mono_domain_lock (domain);
2258 mono_code_manager_commit (domain->code_mp, data, size, newsize);
2259 mono_domain_unlock (domain);
2262 #if defined(__native_client_codegen__) && defined(__native_client__)
2264 * Given the temporary buffer (allocated by mono_domain_code_reserve) into which
2265 * we are generating code, return a pointer to the destination in the dynamic
2266 * code segment into which the code will be copied when mono_domain_code_commit
2268 * LOCKING: Acquires the domain lock.
2271 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2274 mono_domain_lock (domain);
2275 dest = nacl_code_manager_get_code_dest (domain->code_mp, data);
2276 mono_domain_unlock (domain);
2281 * Convenience function which calls mono_domain_code_commit to validate and copy
2282 * the code. The caller sets *buf_base and *buf_size to the start and size of
2283 * the buffer (allocated by mono_domain_code_reserve), and *code_end to the byte
2284 * after the last instruction byte. On return, *buf_base will point to the start
2285 * of the copied in the code segment, and *code_end will point after the end of
2289 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2291 guint8 *tmp = nacl_domain_get_code_dest (domain, *buf_base);
2292 mono_domain_code_commit (domain, *buf_base, buf_size, *code_end - *buf_base);
2293 *code_end = tmp + (*code_end - *buf_base);
2299 /* no-op versions of Native Client functions */
2302 nacl_domain_get_code_dest (MonoDomain *domain, void *data)
2308 nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
2315 * mono_domain_code_foreach:
2316 * Iterate over the code thunks of the code manager of @domain.
2318 * The @func callback MUST not take any locks. If it really needs to, it must respect
2319 * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety
2320 * LOCKING: Acquires the domain lock.
2324 mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data)
2326 mono_domain_lock (domain);
2327 mono_code_manager_foreach (domain->code_mp, func, user_data);
2328 mono_domain_unlock (domain);
2333 mono_context_set (MonoAppContext * new_context)
2335 SET_APPCONTEXT (new_context);
2339 mono_context_get (void)
2341 return GET_APPCONTEXT ();
2344 /* LOCKING: the caller holds the lock for this domain */
2346 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
2348 /* The first entry in the array is the index of the next free slot
2349 * and the total size of the array
2352 if (domain->static_data_array) {
2353 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
2354 next = GPOINTER_TO_INT (domain->static_data_array [0]);
2356 /* 'data' is allocated by alloc_fixed */
2357 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2));
2358 mono_gc_memmove (new_array, domain->static_data_array, sizeof (gpointer) * size);
2360 new_array [1] = GINT_TO_POINTER (size);
2361 mono_gc_free_fixed (domain->static_data_array);
2362 domain->static_data_array = new_array;
2366 gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, MONO_GC_ROOT_DESCR_FOR_FIXED (size));
2368 new_array [0] = GINT_TO_POINTER (next);
2369 new_array [1] = GINT_TO_POINTER (size);
2370 domain->static_data_array = new_array;
2372 domain->static_data_array [next++] = data;
2373 domain->static_data_array [0] = GINT_TO_POINTER (next);
2377 mono_get_corlib (void)
2379 return mono_defaults.corlib;
2383 mono_get_object_class (void)
2385 return mono_defaults.object_class;
2389 mono_get_byte_class (void)
2391 return mono_defaults.byte_class;
2395 mono_get_void_class (void)
2397 return mono_defaults.void_class;
2401 mono_get_boolean_class (void)
2403 return mono_defaults.boolean_class;
2407 mono_get_sbyte_class (void)
2409 return mono_defaults.sbyte_class;
2413 mono_get_int16_class (void)
2415 return mono_defaults.int16_class;
2419 mono_get_uint16_class (void)
2421 return mono_defaults.uint16_class;
2425 mono_get_int32_class (void)
2427 return mono_defaults.int32_class;
2431 mono_get_uint32_class (void)
2433 return mono_defaults.uint32_class;
2437 mono_get_intptr_class (void)
2439 return mono_defaults.int_class;
2443 mono_get_uintptr_class (void)
2445 return mono_defaults.uint_class;
2449 mono_get_int64_class (void)
2451 return mono_defaults.int64_class;
2455 mono_get_uint64_class (void)
2457 return mono_defaults.uint64_class;
2461 mono_get_single_class (void)
2463 return mono_defaults.single_class;
2467 mono_get_double_class (void)
2469 return mono_defaults.double_class;
2473 mono_get_char_class (void)
2475 return mono_defaults.char_class;
2479 mono_get_string_class (void)
2481 return mono_defaults.string_class;
2485 mono_get_enum_class (void)
2487 return mono_defaults.enum_class;
2491 mono_get_array_class (void)
2493 return mono_defaults.array_class;
2497 mono_get_thread_class (void)
2499 return mono_defaults.thread_class;
2503 mono_get_exception_class (void)
2505 return mono_defaults.exception_class;
2509 static char* get_attribute_value (const gchar **attribute_names,
2510 const gchar **attribute_values,
2511 const char *att_name)
2514 for (n=0; attribute_names[n] != NULL; n++) {
2515 if (strcmp (attribute_names[n], att_name) == 0)
2516 return g_strdup (attribute_values[n]);
2521 static void start_element (GMarkupParseContext *context,
2522 const gchar *element_name,
2523 const gchar **attribute_names,
2524 const gchar **attribute_values,
2528 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2530 if (strcmp (element_name, "configuration") == 0) {
2531 app_config->configuration_count++;
2534 if (strcmp (element_name, "startup") == 0) {
2535 app_config->startup_count++;
2539 if (app_config->configuration_count != 1 || app_config->startup_count != 1)
2542 if (strcmp (element_name, "requiredRuntime") == 0) {
2543 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
2544 } else if (strcmp (element_name, "supportedRuntime") == 0) {
2545 char *version = get_attribute_value (attribute_names, attribute_values, "version");
2546 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
2550 static void end_element (GMarkupParseContext *context,
2551 const gchar *element_name,
2555 AppConfigInfo* app_config = (AppConfigInfo*) user_data;
2557 if (strcmp (element_name, "configuration") == 0) {
2558 app_config->configuration_count--;
2559 } else if (strcmp (element_name, "startup") == 0) {
2560 app_config->startup_count--;
2564 static const GMarkupParser
2573 static AppConfigInfo *
2574 app_config_parse (const char *exe_filename)
2576 AppConfigInfo *app_config;
2577 GMarkupParseContext *context;
2580 const char *bundled_config;
2581 char *config_filename;
2583 bundled_config = mono_config_string_for_assembly_file (exe_filename);
2585 if (bundled_config) {
2586 text = g_strdup (bundled_config);
2587 len = strlen (text);
2589 config_filename = g_strconcat (exe_filename, ".config", NULL);
2591 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
2592 g_free (config_filename);
2595 g_free (config_filename);
2598 app_config = g_new0 (AppConfigInfo, 1);
2600 context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
2601 if (g_markup_parse_context_parse (context, text, len, NULL)) {
2602 g_markup_parse_context_end_parse (context, NULL);
2604 g_markup_parse_context_free (context);
2610 app_config_free (AppConfigInfo* app_config)
2613 GSList *list = app_config->supported_runtimes;
2614 while (list != NULL) {
2615 rt = (char*)list->data;
2617 list = g_slist_next (list);
2619 g_slist_free (app_config->supported_runtimes);
2620 g_free (app_config->required_runtime);
2621 g_free (app_config);
2625 static const MonoRuntimeInfo*
2626 get_runtime_by_version (const char *version)
2629 int max = G_N_ELEMENTS (supported_runtimes);
2635 for (n=0; n<max; n++) {
2636 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
2637 return &supported_runtimes[n];
2640 vlen = strlen (version);
2641 if (vlen >= 4 && version [1] - '0' >= 4) {
2642 for (n=0; n<max; n++) {
2643 if (strncmp (version, supported_runtimes[n].runtime_version, 4) == 0)
2644 return &supported_runtimes[n];
2652 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
2654 AppConfigInfo* app_config;
2656 const MonoRuntimeInfo* runtime = NULL;
2657 MonoImage *image = NULL;
2659 app_config = app_config_parse (exe_file);
2661 if (app_config != NULL) {
2662 /* Check supportedRuntime elements, if none is supported, fail.
2663 * If there are no such elements, look for a requiredRuntime element.
2665 if (app_config->supported_runtimes != NULL) {
2667 GSList *list = app_config->supported_runtimes;
2668 while (list != NULL) {
2669 version = (char*) list->data;
2670 runtime = get_runtime_by_version (version);
2671 if (runtime != NULL)
2672 runtimes [n++] = runtime;
2673 list = g_slist_next (list);
2675 runtimes [n] = NULL;
2676 app_config_free (app_config);
2680 /* Check the requiredRuntime element. This is for 1.0 apps only. */
2681 if (app_config->required_runtime != NULL) {
2682 runtimes [0] = get_runtime_by_version (app_config->required_runtime);
2683 runtimes [1] = NULL;
2684 app_config_free (app_config);
2687 app_config_free (app_config);
2690 /* Look for a runtime with the exact version */
2691 image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
2694 image = mono_image_open (exe_file, NULL);
2696 if (image == NULL) {
2697 /* The image is wrong or the file was not found. In this case return
2698 * a default runtime and leave to the initialization method the work of
2699 * reporting the error.
2701 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
2702 runtimes [1] = NULL;
2708 runtimes [0] = get_runtime_by_version (image->version);
2709 runtimes [1] = NULL;
2714 * mono_get_runtime_info:
2716 * Returns: the version of the current runtime instance.
2718 const MonoRuntimeInfo*
2719 mono_get_runtime_info (void)
2721 return current_runtime;
2725 mono_debugger_check_runtime_version (const char *filename)
2727 const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
2728 const MonoRuntimeInfo *rinfo;
2731 get_runtimes_from_exe (filename, &image, runtimes);
2732 rinfo = runtimes [0];
2735 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
2737 if (rinfo != current_runtime)
2738 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
2739 "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
2740 filename, rinfo->runtime_version);
2746 * mono_framework_version:
2748 * Return the major version of the framework curently executing.
2751 mono_framework_version (void)
2753 return current_runtime->framework_version [0] - '0';