Implement mono_gc_alloc_fixed on Boehm to be uncollectable. This matches SGen behavio...
[mono.git] / mono / metadata / domain.c
1 /*
2  * domain.c: MonoDomain functions
3  *
4  * Author:
5  *      Dietmar Maurer (dietmar@ximian.com)
6  *      Patrik Torstensson
7  *
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)
11  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13
14 #include <config.h>
15 #include <glib.h>
16 #include <string.h>
17 #include <sys/stat.h>
18
19 #include <mono/metadata/gc-internals.h>
20
21 #include <mono/utils/atomic.h>
22 #include <mono/utils/mono-compiler.h>
23 #include <mono/utils/mono-logger-internals.h>
24 #include <mono/utils/mono-membar.h>
25 #include <mono/utils/mono-counters.h>
26 #include <mono/utils/hazard-pointer.h>
27 #include <mono/utils/mono-tls.h>
28 #include <mono/utils/mono-mmap.h>
29 #include <mono/utils/mono-threads.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/object-internals.h>
32 #include <mono/metadata/domain-internals.h>
33 #include <mono/metadata/class-internals.h>
34 #include <mono/metadata/assembly.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/metadata-internals.h>
37 #include <mono/metadata/gc-internals.h>
38 #include <mono/metadata/appdomain.h>
39 #include <mono/metadata/mono-debug-debugger.h>
40 #include <mono/metadata/mono-config.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/runtime.h>
43 #include <mono/metadata/w32mutex.h>
44 #include <mono/metadata/w32semaphore.h>
45 #include <mono/metadata/w32event.h>
46 #include <mono/metadata/w32process.h>
47 #include <metadata/threads.h>
48 #include <metadata/profiler-private.h>
49 #include <mono/metadata/coree.h>
50 #include <mono/io-layer/io-layer.h>
51
52 //#define DEBUG_DOMAIN_UNLOAD 1
53
54 #define GET_APPDOMAIN() ((MonoDomain*)mono_tls_get_domain ())
55 #define SET_APPDOMAIN(x) do { \
56         MonoThreadInfo *info; \
57         mono_tls_set_domain (x); \
58         info = mono_thread_info_current (); \
59         if (info) \
60                 mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x));   \
61 } while (FALSE)
62
63 #define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext)
64 #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x))
65
66 static guint16 appdomain_list_size = 0;
67 static guint16 appdomain_next = 0;
68 static MonoDomain **appdomains_list = NULL;
69 static MonoImage *exe_image;
70 static gboolean debug_domain_unload;
71
72 gboolean mono_dont_free_domains;
73
74 #define mono_appdomains_lock() mono_coop_mutex_lock (&appdomains_mutex)
75 #define mono_appdomains_unlock() mono_coop_mutex_unlock (&appdomains_mutex)
76 static MonoCoopMutex appdomains_mutex;
77
78 static MonoDomain *mono_root_domain = NULL;
79
80 /* some statistics */
81 static int max_domain_code_size = 0;
82 static int max_domain_code_alloc = 0;
83 static int total_domain_code_alloc = 0;
84
85 /* AppConfigInfo: Information about runtime versions supported by an 
86  * aplication.
87  */
88 typedef struct {
89         GSList *supported_runtimes;
90         char *required_runtime;
91         int configuration_count;
92         int startup_count;
93 } AppConfigInfo;
94
95 static const MonoRuntimeInfo *current_runtime = NULL;
96
97 /* This is the list of runtime versions supported by this JIT.
98  */
99 static const MonoRuntimeInfo supported_runtimes[] = {
100         {"v4.0.30319","4.5", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
101         {"mobile",    "2.1", { {2,0,5,0}, {10,0,0,0}, {2,0,5,0}, {2,0,5,0} } },
102         {"moonlight", "2.1", { {2,0,5,0}, { 9,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
103 };
104
105
106 /* The stable runtime version */
107 #define DEFAULT_RUNTIME_VERSION "v4.0.30319"
108
109 /* Callbacks installed by the JIT */
110 static MonoCreateDomainFunc create_domain_hook;
111 static MonoFreeDomainFunc free_domain_hook;
112
113 /* AOT cache configuration */
114 static MonoAotCacheConfig aot_cache_config;
115
116 static void
117 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
118
119 static const MonoRuntimeInfo*
120 get_runtime_by_version (const char *version);
121
122 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
123 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
124
125 static LockFreeMempool*
126 lock_free_mempool_new (void)
127 {
128         return g_new0 (LockFreeMempool, 1);
129 }
130
131 static void
132 lock_free_mempool_free (LockFreeMempool *mp)
133 {
134         LockFreeMempoolChunk *chunk, *next;
135
136         chunk = mp->chunks;
137         while (chunk) {
138                 next = (LockFreeMempoolChunk *)chunk->prev;
139                 mono_vfree (chunk, mono_pagesize (), MONO_MEM_ACCOUNT_DOMAIN);
140                 chunk = next;
141         }
142         g_free (mp);
143 }
144
145 /*
146  * This is async safe
147  */
148 static LockFreeMempoolChunk*
149 lock_free_mempool_chunk_new (LockFreeMempool *mp, int len)
150 {
151         LockFreeMempoolChunk *chunk, *prev;
152         int size;
153
154         size = mono_pagesize ();
155         while (size - sizeof (LockFreeMempoolChunk) < len)
156                 size += mono_pagesize ();
157         chunk = (LockFreeMempoolChunk *)mono_valloc (0, size, MONO_MMAP_READ|MONO_MMAP_WRITE, MONO_MEM_ACCOUNT_DOMAIN);
158         g_assert (chunk);
159         chunk->mem = (guint8 *)ALIGN_PTR_TO ((char*)chunk + sizeof (LockFreeMempoolChunk), 16);
160         chunk->size = ((char*)chunk + size) - (char*)chunk->mem;
161         chunk->pos = 0;
162
163         /* Add to list of chunks lock-free */
164         while (TRUE) {
165                 prev = mp->chunks;
166                 if (InterlockedCompareExchangePointer ((volatile gpointer*)&mp->chunks, chunk, prev) == prev)
167                         break;
168         }
169         chunk->prev = prev;
170
171         return chunk;
172 }
173
174 /*
175  * This is async safe
176  */
177 static gpointer
178 lock_free_mempool_alloc0 (LockFreeMempool *mp, guint size)
179 {
180         LockFreeMempoolChunk *chunk;
181         gpointer res;
182         int oldpos;
183
184         // FIXME: Free the allocator
185
186         size = ALIGN_TO (size, 8);
187         chunk = mp->current;
188         if (!chunk) {
189                 chunk = lock_free_mempool_chunk_new (mp, size);
190                 mono_memory_barrier ();
191                 /* Publish */
192                 mp->current = chunk;
193         }
194
195         /* The code below is lock-free, 'chunk' is shared state */
196         oldpos = InterlockedExchangeAdd (&chunk->pos, size);
197         if (oldpos + size > chunk->size) {
198                 chunk = lock_free_mempool_chunk_new (mp, size);
199                 g_assert (chunk->pos + size <= chunk->size);
200                 res = chunk->mem;
201                 chunk->pos += size;
202                 mono_memory_barrier ();
203                 mp->current = chunk;
204         } else {
205                 res = (char*)chunk->mem + oldpos;
206         }
207
208         return res;
209 }
210
211 void
212 mono_install_create_domain_hook (MonoCreateDomainFunc func)
213 {
214         create_domain_hook = func;
215 }
216
217 void
218 mono_install_free_domain_hook (MonoFreeDomainFunc func)
219 {
220         free_domain_hook = func;
221 }
222
223 /**
224  * mono_string_equal:
225  * @s1: First string to compare
226  * @s2: Second string to compare
227  *
228  * Compares two `MonoString*` instances ordinally for equality.
229  *
230  * Returns FALSE if the strings differ.
231  */
232 gboolean
233 mono_string_equal (MonoString *s1, MonoString *s2)
234 {
235         int l1 = mono_string_length (s1);
236         int l2 = mono_string_length (s2);
237
238         if (s1 == s2)
239                 return TRUE;
240         if (l1 != l2)
241                 return FALSE;
242
243         return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0; 
244 }
245
246 /**
247  * mono_string_hash:
248  * @s: the string to hash
249  *
250  * Compute the hash for a `MonoString*`
251  * Returns the hash for the string.
252  */
253 guint
254 mono_string_hash (MonoString *s)
255 {
256         const guint16 *p = mono_string_chars (s);
257         int i, len = mono_string_length (s);
258         guint h = 0;
259
260         for (i = 0; i < len; i++) {
261                 h = (h << 5) - h + *p;
262                 p++;
263         }
264
265         return h;       
266 }
267
268 static gboolean
269 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
270 {
271         int len = GPOINTER_TO_INT (s1 [0]);
272         if (len != GPOINTER_TO_INT (s2 [0]))
273                 return FALSE;
274
275         return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0; 
276 }
277
278 static guint
279 mono_ptrarray_hash (gpointer *s)
280 {
281         int i;
282         int len = GPOINTER_TO_INT (s [0]);
283         guint hash = 0;
284         
285         for (i = 1; i < len; i++)
286                 hash += GPOINTER_TO_UINT (s [i]);
287
288         return hash;    
289 }
290
291 /*
292  * Allocate an id for domain and set domain->domain_id.
293  * LOCKING: must be called while holding appdomains_mutex.
294  * We try to assign low numbers to the domain, so it can be used
295  * as an index in data tables to lookup domain-specific info
296  * with minimal memory overhead. We also try not to reuse the
297  * same id too quickly (to help debugging).
298  */
299 static int
300 domain_id_alloc (MonoDomain *domain)
301 {
302         int id = -1, i;
303         if (!appdomains_list) {
304                 appdomain_list_size = 2;
305                 appdomains_list = (MonoDomain **)mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, "domains list");
306         }
307         for (i = appdomain_next; i < appdomain_list_size; ++i) {
308                 if (!appdomains_list [i]) {
309                         id = i;
310                         break;
311                 }
312         }
313         if (id == -1) {
314                 for (i = 0; i < appdomain_next; ++i) {
315                         if (!appdomains_list [i]) {
316                                 id = i;
317                                 break;
318                         }
319                 }
320         }
321         if (id == -1) {
322                 MonoDomain **new_list;
323                 int new_size = appdomain_list_size * 2;
324                 if (new_size >= (1 << 16))
325                         g_assert_not_reached ();
326                 id = appdomain_list_size;
327                 new_list = (MonoDomain **)mono_gc_alloc_fixed (new_size * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, "domains list");
328                 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
329                 mono_gc_free_fixed (appdomains_list);
330                 appdomains_list = new_list;
331                 appdomain_list_size = new_size;
332         }
333         domain->domain_id = id;
334         appdomains_list [id] = domain;
335         appdomain_next++;
336         if (appdomain_next > appdomain_list_size)
337                 appdomain_next = 0;
338         return id;
339 }
340
341 static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
342 static MonoGCDescriptor domain_gc_desc = MONO_GC_DESCRIPTOR_NULL;
343 static guint32 domain_shadow_serial = 0L;
344
345 /**
346  * mono_domain_create:
347  *
348  * Creates a new application domain, the unmanaged representation
349  * of the actual domain.   Usually you will want to create the
350  *
351  * Application domains provide an isolation facilty for assemblies.   You
352  * can load assemblies and execute code in them that will not be visible
353  * to other application domains.   This is a runtime-based virtualization
354  * technology.
355  *
356  * It is possible to unload domains, which unloads the assemblies and
357  * data that was allocated in that domain.
358  *
359  * When a domain is created a mempool is allocated for domain-specific
360  * structures, along a dedicated code manager to hold code that is
361  * associated with the domain.
362  *
363  * Returns: New initialized MonoDomain, with no configuration or assemblies
364  * loaded into it.
365  */
366 MonoDomain *
367 mono_domain_create (void)
368 {
369         MonoDomain *domain;
370         guint32 shadow_serial;
371   
372         mono_appdomains_lock ();
373         shadow_serial = domain_shadow_serial++;
374   
375         if (!domain_gc_desc) {
376                 unsigned int i, bit = 0;
377                 for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
378                         bit = i / sizeof (gpointer);
379                         domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32);
380                 }
381                 domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
382         }
383         mono_appdomains_unlock ();
384
385 #ifdef HAVE_BOEHM_GC
386         domain = (MonoDomain *)mono_gc_alloc_fixed (sizeof (MonoDomain), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, "domain object");
387 #else
388         domain = (MonoDomain *)mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc, MONO_ROOT_SOURCE_DOMAIN, "domain object");
389         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), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, "misc domain fields");
390 #endif
391         domain->shadow_serial = shadow_serial;
392         domain->domain = NULL;
393         domain->setup = NULL;
394         domain->friendly_name = NULL;
395         domain->search_path = NULL;
396
397         mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
398
399         domain->mp = mono_mempool_new ();
400         domain->code_mp = mono_code_manager_new ();
401         domain->lock_free_mp = lock_free_mempool_new ();
402         domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain environment variables table");
403         domain->domain_assemblies = NULL;
404         domain->assembly_bindings = NULL;
405         domain->assembly_bindings_parsed = FALSE;
406         domain->class_vtable_array = g_ptr_array_new ();
407         domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
408         domain->static_data_array = NULL;
409         mono_jit_code_hash_init (&domain->jit_code_hash);
410         domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain string constants table");
411         domain->num_jit_info_tables = 1;
412         domain->jit_info_table = mono_jit_info_table_new (domain);
413         domain->jit_info_free_queue = NULL;
414         domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
415         domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
416
417         mono_coop_mutex_init_recursive (&domain->lock);
418
419         mono_os_mutex_init_recursive (&domain->assemblies_lock);
420         mono_os_mutex_init_recursive (&domain->jit_code_hash_lock);
421         mono_os_mutex_init_recursive (&domain->finalizable_objects_hash_lock);
422
423         domain->method_rgctx_hash = NULL;
424
425         mono_appdomains_lock ();
426         domain_id_alloc (domain);
427         mono_appdomains_unlock ();
428
429 #ifndef DISABLE_PERFCOUNTERS
430         mono_perfcounters->loader_appdomains++;
431         mono_perfcounters->loader_total_appdomains++;
432 #endif
433
434         mono_debug_domain_create (domain);
435
436         if (create_domain_hook)
437                 create_domain_hook (domain);
438
439         mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
440         
441         return domain;
442 }
443
444 /**
445  * mono_init_internal:
446  * 
447  * Creates the initial application domain and initializes the mono_defaults
448  * structure.
449  * This function is guaranteed to not run any IL code.
450  * If exe_filename is not NULL, the method will determine the required runtime
451  * from the exe configuration file or the version PE field.
452  * If runtime_version is not NULL, that runtime version will be used.
453  * Either exe_filename or runtime_version must be provided.
454  *
455  * Returns: the initial domain.
456  */
457 static MonoDomain *
458 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
459 {
460         static MonoDomain *domain = NULL;
461         MonoAssembly *ass = NULL;
462         MonoImageOpenStatus status = MONO_IMAGE_OK;
463         const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1] = { NULL };
464         int n, dummy;
465
466 #ifdef DEBUG_DOMAIN_UNLOAD
467         debug_domain_unload = TRUE;
468 #endif
469
470         if (domain)
471                 g_assert_not_reached ();
472
473 #if defined(HOST_WIN32) && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
474         /* Avoid system error message boxes. */
475         SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
476 #endif
477
478 #ifndef HOST_WIN32
479         mono_w32handle_init ();
480         mono_w32handle_namespace_init ();
481         wapi_init ();
482 #endif
483
484         mono_w32mutex_init ();
485         mono_w32semaphore_init ();
486         mono_w32event_init ();
487         mono_w32process_init ();
488
489 #ifndef DISABLE_PERFCOUNTERS
490         mono_perfcounters_init ();
491 #endif
492         mono_counters_init ();
493
494         mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
495         mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
496         mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
497
498         mono_gc_base_init ();
499         mono_thread_info_attach (&dummy);
500
501         mono_coop_mutex_init_recursive (&appdomains_mutex);
502
503         mono_metadata_init ();
504         mono_images_init ();
505         mono_assemblies_init ();
506         mono_classes_init ();
507         mono_loader_init ();
508         mono_reflection_init ();
509         mono_runtime_init_tls ();
510
511         domain = mono_domain_create ();
512         mono_root_domain = domain;
513
514         SET_APPDOMAIN (domain);
515         
516         /* Get a list of runtimes supported by the exe */
517         if (exe_filename != NULL) {
518                 /*
519                  * This function will load the exe file as a MonoImage. We need to close it, but
520                  * that would mean it would be reloaded later. So instead, we save it to
521                  * exe_image, and close it during shutdown.
522                  */
523                 get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
524 #ifdef HOST_WIN32
525                 if (!exe_image) {
526                         exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
527                         if (!exe_image)
528                                 exe_image = mono_image_open (exe_filename, NULL);
529                 }
530                 mono_fixup_exe_image (exe_image);
531 #endif
532         } else if (runtime_version != NULL) {
533                 runtimes [0] = get_runtime_by_version (runtime_version);
534                 runtimes [1] = NULL;
535         }
536
537         if (runtimes [0] == NULL) {
538                 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
539                 runtimes [0] = default_runtime;
540                 runtimes [1] = NULL;
541                 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
542                 g_print ("Using default runtime: %s\n", default_runtime->runtime_version); 
543         }
544
545         /* The selected runtime will be the first one for which there is a mscrolib.dll */
546         for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
547                 current_runtime = runtimes [n];
548                 ass = mono_assembly_load_corlib (current_runtime, &status);
549                 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
550                         break;
551
552         }
553         
554         if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
555                 switch (status){
556                 case MONO_IMAGE_ERROR_ERRNO: {
557                         char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
558                         g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
559                         g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
560                         g_free (corlib_file);
561                         break;
562                 }
563                 case MONO_IMAGE_IMAGE_INVALID:
564                         g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
565                                  mono_assembly_getrootdir ());
566                         break;
567                 case MONO_IMAGE_MISSING_ASSEMBLYREF:
568                         g_print ("Missing assembly reference in %s/mscorlib.dll\n",
569                                  mono_assembly_getrootdir ());
570                         break;
571                 case MONO_IMAGE_OK:
572                         /* to suppress compiler warning */
573                         break;
574                 }
575                 
576                 exit (1);
577         }
578         mono_defaults.corlib = mono_assembly_get_image (ass);
579
580         mono_defaults.object_class = mono_class_load_from_name (
581                 mono_defaults.corlib, "System", "Object");
582
583         mono_defaults.void_class = mono_class_load_from_name (
584                 mono_defaults.corlib, "System", "Void");
585
586         mono_defaults.boolean_class = mono_class_load_from_name (
587                 mono_defaults.corlib, "System", "Boolean");
588
589         mono_defaults.byte_class = mono_class_load_from_name (
590                 mono_defaults.corlib, "System", "Byte");
591
592         mono_defaults.sbyte_class = mono_class_load_from_name (
593                 mono_defaults.corlib, "System", "SByte");
594
595         mono_defaults.int16_class = mono_class_load_from_name (
596                 mono_defaults.corlib, "System", "Int16");
597
598         mono_defaults.uint16_class = mono_class_load_from_name (
599                 mono_defaults.corlib, "System", "UInt16");
600
601         mono_defaults.int32_class = mono_class_load_from_name (
602                 mono_defaults.corlib, "System", "Int32");
603
604         mono_defaults.uint32_class = mono_class_load_from_name (
605                 mono_defaults.corlib, "System", "UInt32");
606
607         mono_defaults.uint_class = mono_class_load_from_name (
608                 mono_defaults.corlib, "System", "UIntPtr");
609
610         mono_defaults.int_class = mono_class_load_from_name (
611                 mono_defaults.corlib, "System", "IntPtr");
612
613         mono_defaults.int64_class = mono_class_load_from_name (
614                 mono_defaults.corlib, "System", "Int64");
615
616         mono_defaults.uint64_class = mono_class_load_from_name (
617                 mono_defaults.corlib, "System", "UInt64");
618
619         mono_defaults.single_class = mono_class_load_from_name (
620                 mono_defaults.corlib, "System", "Single");
621
622         mono_defaults.double_class = mono_class_load_from_name (
623                 mono_defaults.corlib, "System", "Double");
624
625         mono_defaults.char_class = mono_class_load_from_name (
626                 mono_defaults.corlib, "System", "Char");
627
628         mono_defaults.string_class = mono_class_load_from_name (
629                 mono_defaults.corlib, "System", "String");
630
631         mono_defaults.enum_class = mono_class_load_from_name (
632                 mono_defaults.corlib, "System", "Enum");
633
634         mono_defaults.array_class = mono_class_load_from_name (
635                 mono_defaults.corlib, "System", "Array");
636
637         mono_defaults.delegate_class = mono_class_load_from_name (
638                 mono_defaults.corlib, "System", "Delegate");
639
640         mono_defaults.multicastdelegate_class = mono_class_load_from_name (
641                 mono_defaults.corlib, "System", "MulticastDelegate");
642
643         mono_defaults.asyncresult_class = mono_class_load_from_name (
644                 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", 
645                 "AsyncResult");
646
647         mono_defaults.manualresetevent_class = mono_class_load_from_name (
648                 mono_defaults.corlib, "System.Threading", "ManualResetEvent");
649
650         mono_defaults.typehandle_class = mono_class_load_from_name (
651                 mono_defaults.corlib, "System", "RuntimeTypeHandle");
652
653         mono_defaults.methodhandle_class = mono_class_load_from_name (
654                 mono_defaults.corlib, "System", "RuntimeMethodHandle");
655
656         mono_defaults.fieldhandle_class = mono_class_load_from_name (
657                 mono_defaults.corlib, "System", "RuntimeFieldHandle");
658
659         mono_defaults.systemtype_class = mono_class_load_from_name (
660                 mono_defaults.corlib, "System", "Type");
661
662         mono_defaults.runtimetype_class = mono_class_load_from_name (
663                 mono_defaults.corlib, "System", "RuntimeType");
664
665         mono_defaults.exception_class = mono_class_load_from_name (
666                 mono_defaults.corlib, "System", "Exception");
667
668         mono_defaults.threadabortexception_class = mono_class_load_from_name (
669                 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
670
671         mono_defaults.thread_class = mono_class_load_from_name (
672                 mono_defaults.corlib, "System.Threading", "Thread");
673
674         mono_defaults.internal_thread_class = mono_class_load_from_name (
675                 mono_defaults.corlib, "System.Threading", "InternalThread");
676
677         mono_defaults.appdomain_class = mono_class_load_from_name (
678                 mono_defaults.corlib, "System", "AppDomain");
679
680 #ifndef DISABLE_REMOTING
681         mono_defaults.transparent_proxy_class = mono_class_load_from_name (
682                 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
683
684         mono_defaults.real_proxy_class = mono_class_load_from_name (
685                 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
686
687         mono_defaults.marshalbyrefobject_class =  mono_class_load_from_name (
688                 mono_defaults.corlib, "System", "MarshalByRefObject");
689
690         mono_defaults.iremotingtypeinfo_class = mono_class_load_from_name (
691                 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
692
693 #endif
694
695         mono_defaults.mono_method_message_class = mono_class_load_from_name (
696                 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
697
698         mono_defaults.field_info_class = mono_class_load_from_name (
699                 mono_defaults.corlib, "System.Reflection", "FieldInfo");
700
701         mono_defaults.method_info_class = mono_class_load_from_name (
702                 mono_defaults.corlib, "System.Reflection", "MethodInfo");
703
704         mono_defaults.stringbuilder_class = mono_class_load_from_name (
705                 mono_defaults.corlib, "System.Text", "StringBuilder");
706
707         mono_defaults.math_class = mono_class_load_from_name (
708                 mono_defaults.corlib, "System", "Math");
709
710         mono_defaults.stack_frame_class = mono_class_load_from_name (
711                 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
712
713         mono_defaults.stack_trace_class = mono_class_load_from_name (
714                 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
715
716         mono_defaults.marshal_class = mono_class_load_from_name (
717                 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
718
719         mono_defaults.typed_reference_class = mono_class_load_from_name (
720                 mono_defaults.corlib, "System", "TypedReference");
721
722         mono_defaults.argumenthandle_class = mono_class_load_from_name (
723                 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
724
725         mono_defaults.monitor_class = mono_class_load_from_name (
726                 mono_defaults.corlib, "System.Threading", "Monitor");
727         /*
728         Not using GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL as this type is heavily checked by sgen when computing finalization.
729         */
730         mono_defaults.critical_finalizer_object = mono_class_try_load_from_name (mono_defaults.corlib,
731                         "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
732
733         mono_assembly_load_friends (ass);
734
735         mono_defaults.handleref_class = mono_class_try_load_from_name (
736                 mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
737
738         mono_defaults.attribute_class = mono_class_load_from_name (
739                 mono_defaults.corlib, "System", "Attribute");
740
741         mono_defaults.customattribute_data_class = mono_class_load_from_name (
742                 mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
743
744         mono_class_init (mono_defaults.array_class);
745         mono_defaults.generic_nullable_class = mono_class_load_from_name (
746                 mono_defaults.corlib, "System", "Nullable`1");
747         mono_defaults.generic_ilist_class = mono_class_load_from_name (
748                 mono_defaults.corlib, "System.Collections.Generic", "IList`1");
749         mono_defaults.generic_ireadonlylist_class = mono_class_load_from_name (
750                 mono_defaults.corlib, "System.Collections.Generic", "IReadOnlyList`1");
751
752         mono_defaults.threadpool_wait_callback_class = mono_class_load_from_name (
753                 mono_defaults.corlib, "System.Threading", "_ThreadPoolWaitCallback");
754
755         mono_defaults.threadpool_perform_wait_callback_method = mono_class_get_method_from_name (
756                 mono_defaults.threadpool_wait_callback_class, "PerformWaitCallback", 0);
757
758         domain->friendly_name = g_path_get_basename (filename);
759
760         mono_profiler_appdomain_name (domain, domain->friendly_name);
761
762         return domain;
763 }
764
765 /**
766  * mono_init:
767  * 
768  * Creates the initial application domain and initializes the mono_defaults
769  * structure.
770  *
771  * This function is guaranteed to not run any IL code.
772  * The runtime is initialized using the default runtime version.
773  *
774  * Returns: the initial domain.
775  */
776 MonoDomain *
777 mono_init (const char *domain_name)
778 {
779         return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
780 }
781
782 /**
783  * mono_init_from_assembly:
784  * @domain_name: name to give to the initial domain
785  * @filename: filename to load on startup
786  *
787  * Used by the runtime, users should use mono_jit_init instead.
788  *
789  * Creates the initial application domain and initializes the mono_defaults
790  * structure.
791  * This function is guaranteed to not run any IL code.
792  * The runtime is initialized using the runtime version required by the
793  * provided executable. The version is determined by looking at the exe 
794  * configuration file and the version PE field)
795  *
796  * Returns: the initial domain.
797  */
798 MonoDomain *
799 mono_init_from_assembly (const char *domain_name, const char *filename)
800 {
801         return mono_init_internal (domain_name, filename, NULL);
802 }
803
804 /**
805  * mono_init_version:
806  * 
807  * Used by the runtime, users should use mono_jit_init instead.
808  * 
809  * Creates the initial application domain and initializes the mono_defaults
810  * structure.
811  *
812  * This function is guaranteed to not run any IL code.
813  * The runtime is initialized using the provided rutime version.
814  *
815  * Returns: the initial domain.
816  */
817 MonoDomain *
818 mono_init_version (const char *domain_name, const char *version)
819 {
820         return mono_init_internal (domain_name, NULL, version);
821 }
822
823 /**
824  * mono_cleanup:
825  *
826  * Cleans up all metadata modules. 
827  */
828 void
829 mono_cleanup (void)
830 {
831         mono_close_exe_image ();
832
833         mono_defaults.corlib = NULL;
834
835         mono_config_cleanup ();
836         mono_loader_cleanup ();
837         mono_classes_cleanup ();
838         mono_assemblies_cleanup ();
839         mono_debug_cleanup ();
840         mono_images_cleanup ();
841         mono_metadata_cleanup ();
842
843         mono_coop_mutex_destroy (&appdomains_mutex);
844
845         mono_w32process_cleanup ();
846
847 #ifndef HOST_WIN32
848         wapi_cleanup ();
849 #endif
850 }
851
852 void
853 mono_close_exe_image (void)
854 {
855         if (exe_image)
856                 mono_image_close (exe_image);
857 }
858
859 /**
860  * mono_get_root_domain:
861  *
862  * The root AppDomain is the initial domain created by the runtime when it is
863  * initialized.  Programs execute on this AppDomain, but can create new ones
864  * later.   Currently there is no unmanaged API to create new AppDomains, this
865  * must be done from managed code.
866  *
867  * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
868  */
869 MonoDomain*
870 mono_get_root_domain (void)
871 {
872         return mono_root_domain;
873 }
874
875 /**
876  * mono_domain_get:
877  *
878  * This method returns the value of the current MonoDomain that this thread
879  * and code are running under.   To obtain the root domain use
880  * mono_get_root_domain() API.
881  *
882  * Returns: the current domain
883  */
884 MonoDomain *
885 mono_domain_get ()
886 {
887         return GET_APPDOMAIN ();
888 }
889
890 void
891 mono_domain_unset (void)
892 {
893         SET_APPDOMAIN (NULL);
894 }
895
896 void
897 mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception)
898 {
899         MonoInternalThread *thread;
900
901         if (mono_domain_get () == domain)
902                 return;
903
904         SET_APPDOMAIN (domain);
905         SET_APPCONTEXT (domain->default_context);
906
907         if (migrate_exception) {
908                 thread = mono_thread_internal_current ();
909                 if (!thread->abort_exc)
910                         return;
911
912                 g_assert (thread->abort_exc->object.vtable->domain != domain);
913                 MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
914                 g_assert (thread->abort_exc->object.vtable->domain == domain);
915         }
916 }
917
918 /**
919  * mono_domain_set_internal:
920  * @domain: the new domain
921  *
922  * Sets the current domain to @domain.
923  */
924 void
925 mono_domain_set_internal (MonoDomain *domain)
926 {
927         mono_domain_set_internal_with_options (domain, TRUE);
928 }
929
930 /**
931  * mono_domain_foreach:
932  * @func: function to invoke with the domain data
933  * @user_data: user-defined pointer that is passed to the supplied @func fo reach domain
934  *
935  * Use this method to safely iterate over all the loaded application
936  * domains in the current runtime.   The provided @func is invoked with a
937  * pointer to the MonoDomain and is given the value of the @user_data
938  * parameter which can be used to pass state to your called routine.
939  */
940 void
941 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
942 {
943         int i, size;
944         MonoDomain **copy;
945
946         /*
947          * Create a copy of the data to avoid calling the user callback
948          * inside the lock because that could lead to deadlocks.
949          * We can do this because this function is not perf. critical.
950          */
951         mono_appdomains_lock ();
952         size = appdomain_list_size;
953         copy = (MonoDomain **)mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, "temporary domains list");
954         memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
955         mono_appdomains_unlock ();
956
957         for (i = 0; i < size; ++i) {
958                 if (copy [i])
959                         func (copy [i], user_data);
960         }
961
962         mono_gc_free_fixed (copy);
963 }
964
965 /**
966  * mono_domain_assembly_open:
967  * @domain: the application domain
968  * @name: file name of the assembly
969  *
970  * fixme: maybe we should integrate this with mono_assembly_open ??
971  */
972 MonoAssembly *
973 mono_domain_assembly_open (MonoDomain *domain, const char *name)
974 {
975         MonoDomain *current;
976         MonoAssembly *ass;
977         GSList *tmp;
978
979         mono_domain_assemblies_lock (domain);
980         for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
981                 ass = (MonoAssembly *)tmp->data;
982                 if (strcmp (name, ass->aname.name) == 0) {
983                         mono_domain_assemblies_unlock (domain);
984                         return ass;
985                 }
986         }
987         mono_domain_assemblies_unlock (domain);
988
989         if (domain != mono_domain_get ()) {
990                 current = mono_domain_get ();
991
992                 mono_domain_set (domain, FALSE);
993                 ass = mono_assembly_open (name, NULL);
994                 mono_domain_set (current, FALSE);
995         } else {
996                 ass = mono_assembly_open (name, NULL);
997         }
998
999         return ass;
1000 }
1001
1002 static void
1003 unregister_vtable_reflection_type (MonoVTable *vtable)
1004 {
1005         MonoObject *type = (MonoObject *)vtable->type;
1006
1007         if (type->vtable->klass != mono_defaults.runtimetype_class)
1008                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type);
1009 }
1010
1011 /**
1012  * mono_domain_free:
1013  * @domain: the domain to release
1014  * @force: if true, it allows the root domain to be released (used at shutdown only).
1015  *
1016  * This releases the resources associated with the specific domain.
1017  * This is a low-level function that is invoked by the AppDomain infrastructure
1018  * when necessary.
1019  */
1020 void
1021 mono_domain_free (MonoDomain *domain, gboolean force)
1022 {
1023         int code_size, code_alloc;
1024         GSList *tmp;
1025         gpointer *p;
1026
1027         if ((domain == mono_root_domain) && !force) {
1028                 g_warning ("cant unload root domain");
1029                 return;
1030         }
1031
1032         if (mono_dont_free_domains)
1033                 return;
1034
1035         mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
1036
1037         mono_debug_domain_unload (domain);
1038
1039         mono_appdomains_lock ();
1040         appdomains_list [domain->domain_id] = NULL;
1041         mono_appdomains_unlock ();
1042
1043         /* must do this early as it accesses fields and types */
1044         if (domain->special_static_fields) {
1045                 mono_alloc_special_static_data_free (domain->special_static_fields);
1046                 g_hash_table_destroy (domain->special_static_fields);
1047                 domain->special_static_fields = NULL;
1048         }
1049
1050         /*
1051          * We must destroy all these hash tables here because they
1052          * contain references to managed objects belonging to the
1053          * domain.  Once we let the GC clear the domain there must be
1054          * no more such references, or we'll crash if a collection
1055          * occurs.
1056          */
1057         mono_g_hash_table_destroy (domain->ldstr_table);
1058         domain->ldstr_table = NULL;
1059
1060         mono_g_hash_table_destroy (domain->env);
1061         domain->env = NULL;
1062
1063         mono_reflection_cleanup_domain (domain);
1064
1065         /* This must be done before type_hash is freed */
1066         if (domain->class_vtable_array) {
1067                 int i;
1068                 for (i = 0; i < domain->class_vtable_array->len; ++i)
1069                         unregister_vtable_reflection_type ((MonoVTable *)g_ptr_array_index (domain->class_vtable_array, i));
1070         }
1071
1072         if (domain->type_hash) {
1073                 mono_g_hash_table_destroy (domain->type_hash);
1074                 domain->type_hash = NULL;
1075         }
1076         if (domain->type_init_exception_hash) {
1077                 mono_g_hash_table_destroy (domain->type_init_exception_hash);
1078                 domain->type_init_exception_hash = NULL;
1079         }
1080
1081         for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1082                 MonoAssembly *ass = (MonoAssembly *)tmp->data;
1083                 mono_assembly_release_gc_roots (ass);
1084         }
1085
1086         /* Have to zero out reference fields since they will be invalidated by the clear_domain () call below */
1087         for (p = (gpointer*)&domain->MONO_DOMAIN_FIRST_OBJECT; p < (gpointer*)&domain->MONO_DOMAIN_FIRST_GC_TRACKED; ++p)
1088                 *p = NULL;
1089
1090         /* This needs to be done before closing assemblies */
1091         mono_gc_clear_domain (domain);
1092
1093         /* Close dynamic assemblies first, since they have no ref count */
1094         for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1095                 MonoAssembly *ass = (MonoAssembly *)tmp->data;
1096                 if (!ass->image || !image_is_dynamic (ass->image))
1097                         continue;
1098                 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);
1099                 if (!mono_assembly_close_except_image_pools (ass))
1100                         tmp->data = NULL;
1101         }
1102
1103         for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1104                 MonoAssembly *ass = (MonoAssembly *)tmp->data;
1105                 if (!ass)
1106                         continue;
1107                 if (!ass->image || image_is_dynamic (ass->image))
1108                         continue;
1109                 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);
1110                 if (!mono_assembly_close_except_image_pools (ass))
1111                         tmp->data = NULL;
1112         }
1113
1114         for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
1115                 MonoAssembly *ass = (MonoAssembly *)tmp->data;
1116                 if (ass)
1117                         mono_assembly_close_finish (ass);
1118         }
1119         g_slist_free (domain->domain_assemblies);
1120         domain->domain_assemblies = NULL;
1121
1122         /* 
1123          * Send this after the assemblies have been unloaded and the domain is still in a 
1124          * usable state.
1125          */
1126         mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
1127
1128         if (free_domain_hook)
1129                 free_domain_hook (domain);
1130
1131         /* FIXME: free delegate_hash_table when it's used */
1132         if (domain->search_path) {
1133                 g_strfreev (domain->search_path);
1134                 domain->search_path = NULL;
1135         }
1136         domain->create_proxy_for_type_method = NULL;
1137         domain->private_invoke_method = NULL;
1138         domain->default_context = NULL;
1139         domain->out_of_memory_ex = NULL;
1140         domain->null_reference_ex = NULL;
1141         domain->stack_overflow_ex = NULL;
1142         domain->ephemeron_tombstone = NULL;
1143         domain->entry_assembly = NULL;
1144
1145         g_free (domain->friendly_name);
1146         domain->friendly_name = NULL;
1147         g_ptr_array_free (domain->class_vtable_array, TRUE);
1148         domain->class_vtable_array = NULL;
1149         g_hash_table_destroy (domain->proxy_vtable_hash);
1150         domain->proxy_vtable_hash = NULL;
1151         if (domain->static_data_array) {
1152                 mono_gc_free_fixed (domain->static_data_array);
1153                 domain->static_data_array = NULL;
1154         }
1155         mono_internal_hash_table_destroy (&domain->jit_code_hash);
1156
1157         /*
1158          * There might still be jit info tables of this domain which
1159          * are not freed.  Since the domain cannot be in use anymore,
1160          * this will free them.
1161          */
1162         mono_thread_hazardous_try_free_all ();
1163         if (domain->aot_modules)
1164                 mono_jit_info_table_free (domain->aot_modules);
1165         g_assert (domain->num_jit_info_tables == 1);
1166         mono_jit_info_table_free (domain->jit_info_table);
1167         domain->jit_info_table = NULL;
1168         g_assert (!domain->jit_info_free_queue);
1169
1170         /* collect statistics */
1171         code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
1172         total_domain_code_alloc += code_alloc;
1173         max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
1174         max_domain_code_size = MAX (max_domain_code_size, code_size);
1175
1176         if (debug_domain_unload) {
1177                 mono_mempool_invalidate (domain->mp);
1178                 mono_code_manager_invalidate (domain->code_mp);
1179         } else {
1180 #ifndef DISABLE_PERFCOUNTERS
1181                 mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
1182 #endif
1183                 mono_mempool_destroy (domain->mp);
1184                 domain->mp = NULL;
1185                 mono_code_manager_destroy (domain->code_mp);
1186                 domain->code_mp = NULL;
1187         }
1188         lock_free_mempool_free (domain->lock_free_mp);
1189         domain->lock_free_mp = NULL;
1190
1191         g_hash_table_destroy (domain->finalizable_objects_hash);
1192         domain->finalizable_objects_hash = NULL;
1193         if (domain->method_rgctx_hash) {
1194                 g_hash_table_destroy (domain->method_rgctx_hash);
1195                 domain->method_rgctx_hash = NULL;
1196         }
1197         if (domain->generic_virtual_cases) {
1198                 g_hash_table_destroy (domain->generic_virtual_cases);
1199                 domain->generic_virtual_cases = NULL;
1200         }
1201         if (domain->ftnptrs_hash) {
1202                 g_hash_table_destroy (domain->ftnptrs_hash);
1203                 domain->ftnptrs_hash = NULL;
1204         }
1205         if (domain->method_to_dyn_method) {
1206                 g_hash_table_destroy (domain->method_to_dyn_method);
1207                 domain->method_to_dyn_method = NULL;
1208         }
1209
1210         mono_os_mutex_destroy (&domain->finalizable_objects_hash_lock);
1211         mono_os_mutex_destroy (&domain->assemblies_lock);
1212         mono_os_mutex_destroy (&domain->jit_code_hash_lock);
1213
1214         mono_coop_mutex_destroy (&domain->lock);
1215
1216         domain->setup = NULL;
1217
1218         mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
1219
1220         /* FIXME: anything else required ? */
1221
1222         mono_gc_free_fixed (domain);
1223
1224 #ifndef DISABLE_PERFCOUNTERS
1225         mono_perfcounters->loader_appdomains--;
1226 #endif
1227
1228         if (domain == mono_root_domain)
1229                 mono_root_domain = NULL;
1230 }
1231
1232 /**
1233  * mono_domain_get_by_id:
1234  * @domainid: the ID
1235  *
1236  * Returns: the domain for a specific domain id.
1237  */
1238 MonoDomain * 
1239 mono_domain_get_by_id (gint32 domainid) 
1240 {
1241         MonoDomain * domain;
1242
1243         mono_appdomains_lock ();
1244         if (domainid < appdomain_list_size)
1245                 domain = appdomains_list [domainid];
1246         else
1247                 domain = NULL;
1248         mono_appdomains_unlock ();
1249
1250         return domain;
1251 }
1252
1253 /*
1254  * mono_domain_get_id:
1255  *
1256  * A domain ID is guaranteed to be unique for as long as the domain
1257  * using it is alive. It may be reused later once the domain has been
1258  * unloaded.
1259  *
1260  * Returns: The unique ID for @domain.
1261  */
1262 gint32
1263 mono_domain_get_id (MonoDomain *domain)
1264 {
1265         return domain->domain_id;
1266 }
1267
1268 /*
1269  * mono_domain_get_friendly_name:
1270  *
1271  * The returned string's lifetime is the same as @domain's. Consider
1272  * copying it if you need to store it somewhere.
1273  *
1274  * Returns: The friendly name of @domain. Can be NULL if not yet set.
1275  */
1276 const char *
1277 mono_domain_get_friendly_name (MonoDomain *domain)
1278 {
1279         return domain->friendly_name;
1280 }
1281
1282 /*
1283  * mono_domain_alloc:
1284  *
1285  * LOCKING: Acquires the domain lock.
1286  */
1287 gpointer
1288 mono_domain_alloc (MonoDomain *domain, guint size)
1289 {
1290         gpointer res;
1291
1292         mono_domain_lock (domain);
1293 #ifndef DISABLE_PERFCOUNTERS
1294         mono_perfcounters->loader_bytes += size;
1295 #endif
1296         res = mono_mempool_alloc (domain->mp, size);
1297         mono_domain_unlock (domain);
1298
1299         return res;
1300 }
1301
1302 /*
1303  * mono_domain_alloc0:
1304  *
1305  * LOCKING: Acquires the domain lock.
1306  */
1307 gpointer
1308 mono_domain_alloc0 (MonoDomain *domain, guint size)
1309 {
1310         gpointer res;
1311
1312         mono_domain_lock (domain);
1313 #ifndef DISABLE_PERFCOUNTERS
1314         mono_perfcounters->loader_bytes += size;
1315 #endif
1316         res = mono_mempool_alloc0 (domain->mp, size);
1317         mono_domain_unlock (domain);
1318
1319         return res;
1320 }
1321
1322 gpointer
1323 mono_domain_alloc0_lock_free (MonoDomain *domain, guint size)
1324 {
1325         return lock_free_mempool_alloc0 (domain->lock_free_mp, size);
1326 }
1327
1328 /*
1329  * mono_domain_code_reserve:
1330  *
1331  * LOCKING: Acquires the domain lock.
1332  */
1333 void*
1334 mono_domain_code_reserve (MonoDomain *domain, int size)
1335 {
1336         gpointer res;
1337
1338         mono_domain_lock (domain);
1339         res = mono_code_manager_reserve (domain->code_mp, size);
1340         mono_domain_unlock (domain);
1341
1342         return res;
1343 }
1344
1345 /*
1346  * mono_domain_code_reserve_align:
1347  *
1348  * LOCKING: Acquires the domain lock.
1349  */
1350 void*
1351 mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment)
1352 {
1353         gpointer res;
1354
1355         mono_domain_lock (domain);
1356         res = mono_code_manager_reserve_align (domain->code_mp, size, alignment);
1357         mono_domain_unlock (domain);
1358
1359         return res;
1360 }
1361
1362 /*
1363  * mono_domain_code_commit:
1364  *
1365  * LOCKING: Acquires the domain lock.
1366  */
1367 void
1368 mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize)
1369 {
1370         mono_domain_lock (domain);
1371         mono_code_manager_commit (domain->code_mp, data, size, newsize);
1372         mono_domain_unlock (domain);
1373 }
1374
1375 /*
1376  * mono_domain_code_foreach:
1377  * Iterate over the code thunks of the code manager of @domain.
1378  * 
1379  * The @func callback MUST not take any locks. If it really needs to, it must respect
1380  * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety 
1381  * LOCKING: Acquires the domain lock.
1382  */
1383
1384 void
1385 mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data)
1386 {
1387         mono_domain_lock (domain);
1388         mono_code_manager_foreach (domain->code_mp, func, user_data);
1389         mono_domain_unlock (domain);
1390 }
1391
1392
1393 void 
1394 mono_context_set (MonoAppContext * new_context)
1395 {
1396         SET_APPCONTEXT (new_context);
1397 }
1398
1399 /**
1400  * mono_context_get:
1401  *
1402  * Returns: the current Mono Application Context.
1403  */
1404 MonoAppContext * 
1405 mono_context_get (void)
1406 {
1407         return GET_APPCONTEXT ();
1408 }
1409
1410 /**
1411  * mono_context_get_id:
1412  * @context: the context to operate on.
1413  *
1414  * Context IDs are guaranteed to be unique for the duration of a Mono
1415  * process; they are never reused.
1416  *
1417  * Returns: The unique ID for @context.
1418  */
1419 gint32
1420 mono_context_get_id (MonoAppContext *context)
1421 {
1422         return context->context_id;
1423 }
1424
1425 /**
1426  * mono_context_get_domain_id:
1427  * @context: the context to operate on.
1428  *
1429  * Returns: The ID of the domain that @context was created in.
1430  */
1431 gint32
1432 mono_context_get_domain_id (MonoAppContext *context)
1433 {
1434         return context->domain_id;
1435 }
1436
1437 /* LOCKING: the caller holds the lock for this domain */
1438 void
1439 mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
1440 {
1441         /* Note [Domain Static Data Array]:
1442          *
1443          * Entry 0 in the array is the index of the next free slot.
1444          * Entry 1 is the total size of the array.
1445          */
1446         int next;
1447         if (domain->static_data_array) {
1448                 int size = GPOINTER_TO_INT (domain->static_data_array [1]);
1449                 next = GPOINTER_TO_INT (domain->static_data_array [0]);
1450                 if (next >= size) {
1451                         /* 'data' is allocated by alloc_fixed */
1452                         gpointer *new_array = (gpointer *)mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2), MONO_ROOT_SOURCE_DOMAIN, "static field list");
1453                         mono_gc_memmove_aligned (new_array, domain->static_data_array, sizeof (gpointer) * size);
1454                         size *= 2;
1455                         new_array [1] = GINT_TO_POINTER (size);
1456                         mono_gc_free_fixed (domain->static_data_array);
1457                         domain->static_data_array = new_array;
1458                 }
1459         } else {
1460                 int size = 32;
1461                 gpointer *new_array = (gpointer *)mono_gc_alloc_fixed (sizeof (gpointer) * size, MONO_GC_ROOT_DESCR_FOR_FIXED (size), MONO_ROOT_SOURCE_DOMAIN, "static field list");
1462                 next = 2;
1463                 new_array [0] = GINT_TO_POINTER (next);
1464                 new_array [1] = GINT_TO_POINTER (size);
1465                 domain->static_data_array = new_array;
1466         }
1467         domain->static_data_array [next++] = data;
1468         domain->static_data_array [0] = GINT_TO_POINTER (next);
1469 }
1470
1471 /**
1472  * mono_get_corlib:
1473  *
1474  * Use this function to get the `MonoImage*` for the mscorlib.dll assembly
1475  *
1476  * Returns: The MonoImage for mscorlib.dll
1477  */
1478 MonoImage*
1479 mono_get_corlib (void)
1480 {
1481         return mono_defaults.corlib;
1482 }
1483
1484 /**
1485  * mono_get_object_class:
1486  *
1487  * Use this function to get the `MonoClass*` that the runtime is using for `System.Object`.
1488  *
1489  * Returns: The `MonoClass*` for the `System.Object` type.
1490  */
1491 MonoClass*
1492 mono_get_object_class (void)
1493 {
1494         return mono_defaults.object_class;
1495 }
1496
1497 /**
1498  * mono_get_byte_class:
1499  *
1500  * Use this function to get the `MonoClass*` that the runtime is using for `System.Byte`.
1501  *
1502  * Returns: The `MonoClass*` for the `System.Byte` type.
1503  */
1504 MonoClass*
1505 mono_get_byte_class (void)
1506 {
1507         return mono_defaults.byte_class;
1508 }
1509
1510 /**
1511  * mono_get_void_class:
1512  *
1513  * Use this function to get the `MonoClass*` that the runtime is using for `System.Void`.
1514  *
1515  * Returns: The `MonoClass*` for the `System.Void` type.
1516  */
1517 MonoClass*
1518 mono_get_void_class (void)
1519 {
1520         return mono_defaults.void_class;
1521 }
1522
1523 /**
1524  * mono_get_boolean_class:
1525  *
1526  * Use this function to get the `MonoClass*` that the runtime is using for `System.Boolean`.
1527  *
1528  * Returns: The `MonoClass*` for the `System.Boolean` type.
1529  */
1530 MonoClass*
1531 mono_get_boolean_class (void)
1532 {
1533         return mono_defaults.boolean_class;
1534 }
1535
1536 /**
1537  * mono_get_sbyte_class:
1538  *
1539  * Use this function to get the `MonoClass*` that the runtime is using for `System.SByte`.
1540  *
1541  * Returns: The `MonoClass*` for the `System.SByte` type.
1542  */
1543 MonoClass*
1544 mono_get_sbyte_class (void)
1545 {
1546         return mono_defaults.sbyte_class;
1547 }
1548
1549 /**
1550  * mono_get_int16_class:
1551  *
1552  * Use this function to get the `MonoClass*` that the runtime is using for `System.Int16`.
1553  *
1554  * Returns: The `MonoClass*` for the `System.Int16` type.
1555  */
1556 MonoClass*
1557 mono_get_int16_class (void)
1558 {
1559         return mono_defaults.int16_class;
1560 }
1561
1562 /**
1563  * mono_get_uint16_class:
1564  *
1565  * Use this function to get the `MonoClass*` that the runtime is using for `System.UInt16`.
1566  *
1567  * Returns: The `MonoClass*` for the `System.UInt16` type.
1568  */
1569 MonoClass*
1570 mono_get_uint16_class (void)
1571 {
1572         return mono_defaults.uint16_class;
1573 }
1574
1575 /**
1576  * mono_get_int32_class:
1577  *
1578  * Use this function to get the `MonoClass*` that the runtime is using for `System.Int32`.
1579  *
1580  * Returns: The `MonoClass*` for the `System.Int32` type.
1581  */
1582 MonoClass*
1583 mono_get_int32_class (void)
1584 {
1585         return mono_defaults.int32_class;
1586 }
1587
1588 /**
1589  * mono_get_uint32_class:
1590  *
1591  * Use this function to get the `MonoClass*` that the runtime is using for `System.UInt32`.
1592  *
1593  * Returns: The `MonoClass*` for the `System.UInt32` type.
1594  */
1595 MonoClass*
1596 mono_get_uint32_class (void)
1597 {
1598         return mono_defaults.uint32_class;
1599 }
1600
1601 /**
1602  * mono_get_intptr_class:
1603  *
1604  * Use this function to get the `MonoClass*` that the runtime is using for `System.IntPtr`.
1605  *
1606  * Returns: The `MonoClass*` for the `System.IntPtr` type.
1607  */
1608 MonoClass*
1609 mono_get_intptr_class (void)
1610 {
1611         return mono_defaults.int_class;
1612 }
1613
1614 /**
1615  * mono_get_uintptr_class:
1616  *
1617  * Use this function to get the `MonoClass*` that the runtime is using for `System.UIntPtr`.
1618  *
1619  * Returns: The `MonoClass*` for the `System.UIntPtr` type.
1620  */
1621 MonoClass*
1622 mono_get_uintptr_class (void)
1623 {
1624         return mono_defaults.uint_class;
1625 }
1626
1627 /**
1628  * mono_get_int64_class:
1629  *
1630  * Use this function to get the `MonoClass*` that the runtime is using for `System.Int64`.
1631  *
1632  * Returns: The `MonoClass*` for the `System.Int64` type.
1633  */
1634 MonoClass*
1635 mono_get_int64_class (void)
1636 {
1637         return mono_defaults.int64_class;
1638 }
1639
1640 /**
1641  * mono_get_uint64_class:
1642  *
1643  * Use this function to get the `MonoClass*` that the runtime is using for `System.UInt64`.
1644  *
1645  * Returns: The `MonoClass*` for the `System.UInt64` type.
1646  */
1647 MonoClass*
1648 mono_get_uint64_class (void)
1649 {
1650         return mono_defaults.uint64_class;
1651 }
1652
1653 /**
1654  * mono_get_single_class:
1655  *
1656  * Use this function to get the `MonoClass*` that the runtime is using for `System.Single` (32-bit floating points).
1657  *
1658  * Returns: The `MonoClass*` for the `System.Single` type.
1659  */
1660 MonoClass*
1661 mono_get_single_class (void)
1662 {
1663         return mono_defaults.single_class;
1664 }
1665
1666 /**
1667  * mono_get_double_class:
1668  *
1669  * Use this function to get the `MonoClass*` that the runtime is using for `System.Double` (64-bit floating points).
1670  *
1671  * Returns: The `MonoClass*` for the `System.Double` type.
1672  */
1673 MonoClass*
1674 mono_get_double_class (void)
1675 {
1676         return mono_defaults.double_class;
1677 }
1678
1679 /**
1680  * mono_get_char_class:
1681  *
1682  * Use this function to get the `MonoClass*` that the runtime is using for `System.Char`.
1683  *
1684  * Returns: The `MonoClass*` for the `System.Char` type.
1685  */
1686 MonoClass*
1687 mono_get_char_class (void)
1688 {
1689         return mono_defaults.char_class;
1690 }
1691
1692 /**
1693  * mono_get_string_class:
1694  *
1695  * Use this function to get the `MonoClass*` that the runtime is using for `System.String`.
1696  *
1697  * Returns: The `MonoClass*` for the `System.String` type.
1698  */
1699 MonoClass*
1700 mono_get_string_class (void)
1701 {
1702         return mono_defaults.string_class;
1703 }
1704
1705 /**
1706  * mono_get_enum_class:
1707  *
1708  * Use this function to get the `MonoClass*` that the runtime is using for `System.Enum`.
1709  *
1710  * Returns: The `MonoClass*` for the `System.Enum` type.
1711  */
1712 MonoClass*
1713 mono_get_enum_class (void)
1714 {
1715         return mono_defaults.enum_class;
1716 }
1717
1718 /**
1719  * mono_get_array_class:
1720  *
1721  * Use this function to get the `MonoClass*` that the runtime is using for `System.Array`.
1722  *
1723  * Returns: The `MonoClass*` for the `System.Array` type.
1724  */
1725 MonoClass*
1726 mono_get_array_class (void)
1727 {
1728         return mono_defaults.array_class;
1729 }
1730
1731 /**
1732  * mono_get_thread_class:
1733  *
1734  * Use this function to get the `MonoClass*` that the runtime is using for `System.Threading.Thread`.
1735  *
1736  * Returns: The `MonoClass*` for the `System.Threading.Thread` type.
1737  */
1738 MonoClass*
1739 mono_get_thread_class (void)
1740 {
1741         return mono_defaults.thread_class;
1742 }
1743
1744 /**
1745  * mono_get_exception_class:
1746  *
1747  * Use this function to get the `MonoClass*` that the runtime is using for `System.Exception`.
1748  *
1749  * Returns: The `MonoClass*` for the `` type.
1750  */
1751 MonoClass*
1752 mono_get_exception_class (void)
1753 {
1754         return mono_defaults.exception_class;
1755 }
1756
1757
1758 static char* get_attribute_value (const gchar **attribute_names, 
1759                                         const gchar **attribute_values, 
1760                                         const char *att_name)
1761 {
1762         int n;
1763         for (n=0; attribute_names[n] != NULL; n++) {
1764                 if (strcmp (attribute_names[n], att_name) == 0)
1765                         return g_strdup (attribute_values[n]);
1766         }
1767         return NULL;
1768 }
1769
1770 static void start_element (GMarkupParseContext *context, 
1771                            const gchar         *element_name,
1772                            const gchar        **attribute_names,
1773                            const gchar        **attribute_values,
1774                            gpointer             user_data,
1775                            GError             **error)
1776 {
1777         AppConfigInfo* app_config = (AppConfigInfo*) user_data;
1778         
1779         if (strcmp (element_name, "configuration") == 0) {
1780                 app_config->configuration_count++;
1781                 return;
1782         }
1783         if (strcmp (element_name, "startup") == 0) {
1784                 app_config->startup_count++;
1785                 return;
1786         }
1787         
1788         if (app_config->configuration_count != 1 || app_config->startup_count != 1)
1789                 return;
1790         
1791         if (strcmp (element_name, "requiredRuntime") == 0) {
1792                 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
1793         } else if (strcmp (element_name, "supportedRuntime") == 0) {
1794                 char *version = get_attribute_value (attribute_names, attribute_values, "version");
1795                 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
1796         }
1797 }
1798
1799 static void end_element   (GMarkupParseContext *context,
1800                            const gchar         *element_name,
1801                            gpointer             user_data,
1802                            GError             **error)
1803 {
1804         AppConfigInfo* app_config = (AppConfigInfo*) user_data;
1805         
1806         if (strcmp (element_name, "configuration") == 0) {
1807                 app_config->configuration_count--;
1808         } else if (strcmp (element_name, "startup") == 0) {
1809                 app_config->startup_count--;
1810         }
1811 }
1812
1813 static const GMarkupParser 
1814 mono_parser = {
1815         start_element,
1816         end_element,
1817         NULL,
1818         NULL,
1819         NULL
1820 };
1821
1822 static AppConfigInfo *
1823 app_config_parse (const char *exe_filename)
1824 {
1825         AppConfigInfo *app_config;
1826         GMarkupParseContext *context;
1827         char *text;
1828         gsize len;
1829         const char *bundled_config;
1830         char *config_filename;
1831
1832         bundled_config = mono_config_string_for_assembly_file (exe_filename);
1833
1834         if (bundled_config) {
1835                 text = g_strdup (bundled_config);
1836                 len = strlen (text);
1837         } else {
1838                 config_filename = g_strconcat (exe_filename, ".config", NULL);
1839
1840                 if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
1841                         g_free (config_filename);
1842                         return NULL;
1843                 }
1844                 g_free (config_filename);
1845         }
1846
1847         app_config = g_new0 (AppConfigInfo, 1);
1848
1849         context = g_markup_parse_context_new (&mono_parser, (GMarkupParseFlags)0, app_config, NULL);
1850         if (g_markup_parse_context_parse (context, text, len, NULL)) {
1851                 g_markup_parse_context_end_parse (context, NULL);
1852         }
1853         g_markup_parse_context_free (context);
1854         g_free (text);
1855         return app_config;
1856 }
1857
1858 static void 
1859 app_config_free (AppConfigInfo* app_config)
1860 {
1861         char *rt;
1862         GSList *list = app_config->supported_runtimes;
1863         while (list != NULL) {
1864                 rt = (char*)list->data;
1865                 g_free (rt);
1866                 list = g_slist_next (list);
1867         }
1868         g_slist_free (app_config->supported_runtimes);
1869         g_free (app_config->required_runtime);
1870         g_free (app_config);
1871 }
1872
1873
1874 static const MonoRuntimeInfo*
1875 get_runtime_by_version (const char *version)
1876 {
1877         int n;
1878         int max = G_N_ELEMENTS (supported_runtimes);
1879         int vlen;
1880
1881         if (!version)
1882                 return NULL;
1883
1884         for (n=0; n<max; n++) {
1885                 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
1886                         return &supported_runtimes[n];
1887         }
1888         
1889         vlen = strlen (version);
1890         if (vlen >= 4 && version [1] - '0' >= 4) {
1891                 for (n=0; n<max; n++) {
1892                         if (strncmp (version, supported_runtimes[n].runtime_version, 4) == 0)
1893                                 return &supported_runtimes[n];
1894                 }
1895         }
1896         
1897         return NULL;
1898 }
1899
1900 static void
1901 get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
1902 {
1903         AppConfigInfo* app_config;
1904         char *version;
1905         const MonoRuntimeInfo* runtime = NULL;
1906         MonoImage *image = NULL;
1907         
1908         app_config = app_config_parse (exe_file);
1909         
1910         if (app_config != NULL) {
1911                 /* Check supportedRuntime elements, if none is supported, fail.
1912                  * If there are no such elements, look for a requiredRuntime element.
1913                  */
1914                 if (app_config->supported_runtimes != NULL) {
1915                         int n = 0;
1916                         GSList *list = app_config->supported_runtimes;
1917                         while (list != NULL) {
1918                                 version = (char*) list->data;
1919                                 runtime = get_runtime_by_version (version);
1920                                 if (runtime != NULL)
1921                                         runtimes [n++] = runtime;
1922                                 list = g_slist_next (list);
1923                         }
1924                         runtimes [n] = NULL;
1925                         app_config_free (app_config);
1926                         return;
1927                 }
1928                 
1929                 /* Check the requiredRuntime element. This is for 1.0 apps only. */
1930                 if (app_config->required_runtime != NULL) {
1931                         runtimes [0] = get_runtime_by_version (app_config->required_runtime);
1932                         runtimes [1] = NULL;
1933                         app_config_free (app_config);
1934                         return;
1935                 }
1936                 app_config_free (app_config);
1937         }
1938         
1939         /* Look for a runtime with the exact version */
1940         image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
1941
1942         if (image == NULL)
1943                 image = mono_image_open (exe_file, NULL);
1944
1945         if (image == NULL) {
1946                 /* The image is wrong or the file was not found. In this case return
1947                  * a default runtime and leave to the initialization method the work of
1948                  * reporting the error.
1949                  */
1950                 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1951                 runtimes [1] = NULL;
1952                 return;
1953         }
1954
1955         *exe_image = image;
1956
1957         runtimes [0] = get_runtime_by_version (image->version);
1958         runtimes [1] = NULL;
1959 }
1960
1961
1962 /**
1963  * mono_get_runtime_info:
1964  *
1965  * Returns: the version of the current runtime instance.
1966  */
1967 const MonoRuntimeInfo*
1968 mono_get_runtime_info (void)
1969 {
1970         return current_runtime;
1971 }
1972
1973 /**
1974  * mono_framework_version:
1975  *
1976  * Return the major version of the framework curently executing.
1977  */
1978 int
1979 mono_framework_version (void)
1980 {
1981         return current_runtime->framework_version [0] - '0';
1982 }
1983
1984 void
1985 mono_enable_debug_domain_unload (gboolean enable)
1986 {
1987         debug_domain_unload = enable;
1988 }
1989
1990 MonoAotCacheConfig *
1991 mono_get_aot_cache_config (void)
1992 {
1993         return &aot_cache_config;
1994 }
1995
1996 void
1997 mono_domain_lock (MonoDomain *domain)
1998 {
1999         mono_locks_coop_acquire (&domain->lock, DomainLock);
2000 }
2001
2002 void
2003 mono_domain_unlock (MonoDomain *domain)
2004 {
2005         mono_locks_coop_release (&domain->lock, DomainLock);
2006 }
2007
2008 GPtrArray*
2009 mono_domain_get_assemblies (MonoDomain *domain, gboolean refonly)
2010 {
2011         GSList *tmp;
2012         GPtrArray *assemblies;
2013         MonoAssembly *ass;
2014
2015         assemblies = g_ptr_array_new ();
2016         mono_domain_assemblies_lock (domain);
2017         for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
2018                 ass = (MonoAssembly *)tmp->data;
2019                 if (refonly != ass->ref_only)
2020                         continue;
2021                 if (ass->corlib_internal)
2022                         continue;
2023                 g_ptr_array_add (assemblies, ass);
2024         }
2025         mono_domain_assemblies_unlock (domain);
2026         return assemblies;
2027 }