2 * appdomain.c: AppDomain functions
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2001 Ximian, Inc.
18 #include <mono/metadata/object.h>
19 #include <mono/metadata/appdomain.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/exception.h>
22 #include <mono/metadata/cil-coff.h>
24 static guint32 appdomain_thread_id = 0;
26 static MonoJitInfoTable *
27 mono_jit_info_table_new ()
29 return g_array_new (FALSE, FALSE, sizeof (gpointer));
33 mono_jit_info_table_free (MonoJitInfoTable *table)
35 g_array_free (table, TRUE);
39 mono_jit_info_table_index (MonoJitInfoTable *table, gpointer addr)
41 int left = 0, right = table->len;
43 while (left < right) {
44 int pos = (left + right) / 2;
45 MonoJitInfo *ji = g_array_index (table, gpointer, pos);
46 gpointer start = ji->code_start;
47 gpointer end = start + ji->code_size;
61 mono_jit_info_table_find (MonoDomain *domain, gpointer addr)
63 MonoJitInfoTable *table = domain->jit_info_table;
64 int left = 0, right = table->len;
66 while (left < right) {
67 int pos = (left + right) / 2;
68 MonoJitInfo *ji = g_array_index (table, gpointer, pos);
69 gpointer start = ji->code_start;
70 gpointer end = start + ji->code_size;
80 /* maybe irt is shared code, so we also search in the root domain */
81 if (domain != mono_root_domain)
82 return mono_jit_info_table_find (domain, addr);
88 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
90 MonoJitInfoTable *table = domain->jit_info_table;
91 gpointer start = ji->code_start;
92 int pos = mono_jit_info_table_index (table, start);
94 g_array_insert_val (table, pos, ji);
98 ldstr_hash (const char* str)
102 len = mono_metadata_decode_blob_size (str, &str) - 1;
106 * FIXME: The distribution may not be so nice with lots of
107 * null chars in the string.
109 for (str += 1; str < end; str++)
110 h = (h << 5) - h + *str;
115 ldstr_equal (const char *str1, const char *str2) {
117 len = mono_metadata_decode_blob_size (str1, NULL) - 1;
118 len2 = mono_metadata_decode_blob_size (str2, NULL) - 1;
121 return memcmp (str1, str2, len) == 0;
126 domain_finalizer (void *obj, void *data) {
127 g_print ("domain finalized\n");
132 mono_create_domain ()
137 domain = GC_malloc (sizeof (MonoDomain));
138 GC_register_finalizer (domain, domain_finalizer, NULL, NULL, NULL);
140 domain = g_new0 (MonoDomain, 1);
142 domain->domain = NULL;
143 domain->setup = NULL;
144 domain->friendly_name = NULL;
146 domain->mp = mono_mempool_new ();
147 domain->env = g_hash_table_new (g_str_hash, g_str_equal);
148 domain->assemblies = g_hash_table_new (g_str_hash, g_str_equal);
149 domain->class_vtable_hash = mono_g_hash_table_new (NULL, NULL);
150 domain->jit_code_hash = g_hash_table_new (NULL, NULL);
151 domain->ldstr_table = mono_g_hash_table_new ((GHashFunc)ldstr_hash, (GCompareFunc)ldstr_equal);
152 domain->jit_info_table = mono_jit_info_table_new ();
156 MonoDomain *mono_root_domain = NULL;
161 * Creates the initial application domain and initializes the mono_defaults
164 * Returns: the initial domain.
167 mono_init (const char *filename)
169 static MonoDomain *domain = NULL;
170 MonoAppDomainSetup *setup;
175 enum MonoImageOpenStatus status = MONO_IMAGE_OK;
178 g_assert_not_reached ();
180 appdomain_thread_id = TlsAlloc ();
182 domain = mono_create_domain ();
183 mono_root_domain = domain;
185 TlsSetValue (appdomain_thread_id, domain);
187 /* find the corlib */
188 ass = mono_assembly_open (CORLIB_NAME, NULL, &status);
189 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
191 case MONO_IMAGE_ERROR_ERRNO:
192 g_print ("The assembly corlib.dll was not found or could not be loaded.\n");
193 g_print ("It should have been installed in the `%s' directory.\n", MONO_ASSEMBLIES);
195 case MONO_IMAGE_IMAGE_INVALID:
196 g_print ("The file %s/corlib.dll is an invalid CIL image\n", MONO_ASSEMBLIES);
198 case MONO_IMAGE_MISSING_ASSEMBLYREF:
199 g_print ("Minning assembly reference in %s/corlib.dll\n", MONO_ASSEMBLIES);
202 /* to suppress compiler warning */
207 mono_defaults.corlib = ass->image;
209 mono_defaults.object_class = mono_class_from_name (
210 mono_defaults.corlib, "System", "Object");
211 g_assert (mono_defaults.object_class != 0);
213 mono_defaults.void_class = mono_class_from_name (
214 mono_defaults.corlib, "System", "Void");
215 g_assert (mono_defaults.void_class != 0);
217 mono_defaults.boolean_class = mono_class_from_name (
218 mono_defaults.corlib, "System", "Boolean");
219 g_assert (mono_defaults.boolean_class != 0);
221 mono_defaults.byte_class = mono_class_from_name (
222 mono_defaults.corlib, "System", "Byte");
223 g_assert (mono_defaults.byte_class != 0);
225 mono_defaults.sbyte_class = mono_class_from_name (
226 mono_defaults.corlib, "System", "SByte");
227 g_assert (mono_defaults.sbyte_class != 0);
229 mono_defaults.int16_class = mono_class_from_name (
230 mono_defaults.corlib, "System", "Int16");
231 g_assert (mono_defaults.int16_class != 0);
233 mono_defaults.uint16_class = mono_class_from_name (
234 mono_defaults.corlib, "System", "UInt16");
235 g_assert (mono_defaults.uint16_class != 0);
237 mono_defaults.int32_class = mono_class_from_name (
238 mono_defaults.corlib, "System", "Int32");
239 g_assert (mono_defaults.int32_class != 0);
241 mono_defaults.uint32_class = mono_class_from_name (
242 mono_defaults.corlib, "System", "UInt32");
243 g_assert (mono_defaults.uint32_class != 0);
245 mono_defaults.uint_class = mono_class_from_name (
246 mono_defaults.corlib, "System", "UIntPtr");
247 g_assert (mono_defaults.uint_class != 0);
249 mono_defaults.int_class = mono_class_from_name (
250 mono_defaults.corlib, "System", "IntPtr");
251 g_assert (mono_defaults.int_class != 0);
253 mono_defaults.int64_class = mono_class_from_name (
254 mono_defaults.corlib, "System", "Int64");
255 g_assert (mono_defaults.int64_class != 0);
257 mono_defaults.uint64_class = mono_class_from_name (
258 mono_defaults.corlib, "System", "UInt64");
259 g_assert (mono_defaults.uint64_class != 0);
261 mono_defaults.single_class = mono_class_from_name (
262 mono_defaults.corlib, "System", "Single");
263 g_assert (mono_defaults.single_class != 0);
265 mono_defaults.double_class = mono_class_from_name (
266 mono_defaults.corlib, "System", "Double");
267 g_assert (mono_defaults.double_class != 0);
269 mono_defaults.char_class = mono_class_from_name (
270 mono_defaults.corlib, "System", "Char");
271 g_assert (mono_defaults.char_class != 0);
273 mono_defaults.string_class = mono_class_from_name (
274 mono_defaults.corlib, "System", "String");
275 g_assert (mono_defaults.string_class != 0);
277 mono_defaults.enum_class = mono_class_from_name (
278 mono_defaults.corlib, "System", "Enum");
279 g_assert (mono_defaults.enum_class != 0);
281 mono_defaults.array_class = mono_class_from_name (
282 mono_defaults.corlib, "System", "Array");
283 g_assert (mono_defaults.array_class != 0);
285 mono_defaults.multicastdelegate_class = mono_class_from_name (
286 mono_defaults.corlib, "System", "MulticastDelegate");
287 g_assert (mono_defaults.multicastdelegate_class != 0 );
289 mono_defaults.asyncresult_class = mono_class_from_name (
290 mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
292 g_assert (mono_defaults.asyncresult_class != 0 );
294 mono_defaults.waithandle_class = mono_class_from_name (
295 mono_defaults.corlib, "System.Threading", "WaitHandle");
296 g_assert (mono_defaults.waithandle_class != 0 );
298 mono_defaults.typehandle_class = mono_class_from_name (
299 mono_defaults.corlib, "System", "RuntimeTypeHandle");
300 g_assert (mono_defaults.typehandle_class != 0);
302 mono_defaults.methodhandle_class = mono_class_from_name (
303 mono_defaults.corlib, "System", "RuntimeMethodHandle");
304 g_assert (mono_defaults.methodhandle_class != 0);
306 mono_defaults.fieldhandle_class = mono_class_from_name (
307 mono_defaults.corlib, "System", "RuntimeFieldHandle");
308 g_assert (mono_defaults.fieldhandle_class != 0);
310 mono_defaults.monotype_class = mono_class_from_name (
311 mono_defaults.corlib, "System", "MonoType");
312 g_assert (mono_defaults.monotype_class != 0);
314 mono_defaults.exception_class = mono_class_from_name (
315 mono_defaults.corlib, "System", "Exception");
316 g_assert (mono_defaults.exception_class != 0);
318 mono_defaults.thread_class = mono_class_from_name (
319 mono_defaults.corlib, "System.Threading", "Thread");
320 g_assert (mono_defaults.thread_class != 0);
322 class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
323 setup = (MonoAppDomainSetup *) mono_object_new (domain, class);
324 ves_icall_System_AppDomainSetup_InitAppDomainSetup (setup);
326 name = mono_string_new (domain, g_path_get_basename (filename));
328 class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
329 ad = (MonoAppDomain *) mono_object_new (domain, class);
332 domain->setup = setup;
333 domain->friendly_name = name;
339 ves_icall_System_AppDomainSetup_InitAppDomainSetup (MonoAppDomainSetup *setup)
341 // fixme: implement me
345 * mono_domain_transfer_object:
346 * @src: the source domain
347 * @dst: the destination domain
348 * @obj: the object to transfer
350 * This function is used to transfer objects between domains. This is done by
351 * marshalling or serialisation.
354 mono_domain_transfer_object (MonoDomain *src, MonoDomain *dst, MonoObject *obj)
362 g_assert (obj->vtable->domain == src);
364 /* fixme: transfer an object from one domain into another */
366 klass = obj->vtable->klass;
368 if (MONO_CLASS_IS_ARRAY (klass)) {
369 MonoArray *ao = (MonoArray *)obj;
370 int esize, ecount, i;
373 sizes = alloca (klass->rank * sizeof(guint32) * 2);
374 esize = mono_array_element_size (klass);
376 for (i = 0; i < klass->rank; ++i) {
377 sizes [i] = ao->bounds [i].length;
378 ecount *= ao->bounds [i].length;
379 sizes [i + klass->rank] = ao->bounds [i].lower_bound;
381 res = (MonoObject *)mono_array_new_full (dst, klass, sizes, sizes + klass->rank);
382 if (klass->element_class->valuetype) {
383 memcpy (res, (char *)ao + sizeof(MonoArray), esize * ecount);
385 g_assert (esize == sizeof (gpointer));
386 for (i = 0; i < ecount; i++) {
387 int offset = sizeof (MonoArray) + esize * i;
388 gpointer *src_ea = (gpointer *)((char *)ao + offset);
389 gpointer *dst_ea = (gpointer *)((char *)res + offset);
391 *dst_ea = mono_domain_transfer_object (src, dst, *src_ea);
394 } else if (klass == mono_defaults.string_class) {
395 MonoString *str = (MonoString *)obj;
396 res = (MonoObject *)mono_string_new_utf16 (dst,
397 (const guint16 *)str->c_str->vector, str->length);
399 // fixme: we need generic marshalling code here */
400 g_assert_not_reached ();
407 ves_icall_System_AppDomain_GetData (MonoAppDomain *ad, MonoString *name)
409 MonoDomain *add = ad->data;
410 MonoDomain *cur = mono_domain_get ();
414 g_assert (ad != NULL);
415 g_assert (name != NULL);
417 str = mono_string_to_utf8 (name);
419 if (!strcmp (str, "APPBASE"))
420 o = (MonoObject *)add->setup->application_base;
421 else if (!strcmp (str, "APP_CONFIG_FILE"))
422 o = (MonoObject *)add->setup->configuration_file;
423 else if (!strcmp (str, "DYNAMIC_BASE"))
424 o = (MonoObject *)add->setup->dynamic_base;
425 else if (!strcmp (str, "APP_NAME"))
426 o = (MonoObject *)add->setup->application_name;
427 else if (!strcmp (str, "CACHE_BASE"))
428 o = (MonoObject *)add->setup->cache_path;
429 else if (!strcmp (str, "PRIVATE_BINPATH"))
430 o = (MonoObject *)add->setup->private_bin_path;
431 else if (!strcmp (str, "BINPATH_PROBE_ONLY"))
432 o = (MonoObject *)add->setup->private_bin_path_probe;
433 else if (!strcmp (str, "SHADOW_COPY_DIRS"))
434 o = (MonoObject *)add->setup->shadow_copy_directories;
435 else if (!strcmp (str, "FORCE_CACHE_INSTALL"))
436 o = (MonoObject *)add->setup->shadow_copy_files;
438 o = g_hash_table_lookup (add->env, str);
445 return mono_domain_transfer_object (add, cur, o);
449 ves_icall_System_AppDomain_SetData (MonoAppDomain *ad, MonoString *name, MonoObject *data)
451 MonoDomain *add = ad->data;
452 MonoDomain *cur = mono_domain_get ();
456 g_assert (ad != NULL);
457 g_assert (name != NULL);
459 o = mono_domain_transfer_object (cur, add, data);
461 /* fixme: need a hash func for MonoString */
462 str = mono_string_to_utf8 (name);
463 g_hash_table_insert (add->env, str, o);
468 ves_icall_System_AppDomain_getSetup (MonoAppDomain *ad)
470 g_assert (ad != NULL);
471 g_assert (ad->data != NULL);
473 return ad->data->setup;
477 ves_icall_System_AppDomain_getFriendlyName (MonoAppDomain *ad)
479 g_assert (ad != NULL);
480 g_assert (ad->data != NULL);
482 return ad->data->friendly_name;
488 * Returns the current domain.
493 return ((MonoDomain *)TlsGetValue (appdomain_thread_id));
498 * @domain: the new domain
500 * Sets the current domain to @domain.
503 mono_domain_set (MonoDomain *domain)
505 TlsSetValue (appdomain_thread_id, domain);
509 ves_icall_System_AppDomain_getCurDomain ()
511 MonoDomain *add = mono_domain_get ();
516 ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomainSetup *setup)
518 MonoDomain *domain = mono_domain_get ();
523 adclass = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
525 // fixme: pin all those objects
526 ad = (MonoAppDomain *) mono_object_new (domain, adclass);
527 ad->data = data = mono_create_domain ();
530 data->friendly_name = friendly_name;
532 // fixme: what to do next ?
541 } add_assembly_helper_t;
544 add_assembly (gpointer key, gpointer value, gpointer user_data)
546 add_assembly_helper_t *ah = (add_assembly_helper_t *) user_data;
548 mono_array_set (ah->res, gpointer, ah->idx++, mono_assembly_get_object (ah->domain, value));
552 ves_icall_System_AppDomain_GetAssemblies (MonoAppDomain *ad)
554 MonoDomain *domain = ad->data;
555 static MonoClass *System_Reflection_Assembly;
557 add_assembly_helper_t ah;
559 if (!System_Reflection_Assembly)
560 System_Reflection_Assembly = mono_class_from_name (
561 mono_defaults.corlib, "System.Reflection", "Assembly");
563 res = mono_array_new (domain, System_Reflection_Assembly, g_hash_table_size (domain->assemblies));
568 g_hash_table_foreach (domain->assemblies, add_assembly, &ah);
574 MonoReflectionAssembly *
575 ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad, MonoReflectionAssemblyName *assRef, MonoObject *evidence)
577 MonoDomain *domain = ad->data;
578 char *name, *filename;
579 enum MonoImageOpenStatus status = MONO_IMAGE_OK;
582 /* FIXME : examine evidence? */
584 g_assert (assRef != NULL);
585 g_assert (assRef->name != NULL);
587 /* FIXME : examine version, culture info */
589 name = filename = mono_string_to_utf8 (assRef->name);
591 if (strncmp (filename, "file://", 7) == 0)
594 ass = mono_assembly_open (filename, NULL, &status);
599 mono_raise_exception ((MonoException *)mono_exception_from_name (mono_defaults.corlib, "System.IO", "FileNotFoundException"));
601 return mono_assembly_get_object (domain, ass);
605 ves_icall_System_AppDomain_Unload (MonoAppDomain *ad)
607 mono_domain_unload (ad->data, FALSE);
611 * mono_domain_assembly_open:
612 * @domain: the application domain
613 * @name: file name of the assembly
615 * fixme: maybe we should integrate this with mono_assembly_open ??
618 mono_domain_assembly_open (MonoDomain *domain, char *name)
620 MonoAssembly *ass, *tmp;
623 if ((ass = g_hash_table_lookup (domain->assemblies, name)))
626 if (!(ass = mono_assembly_open (name, NULL, NULL)))
629 g_hash_table_insert (domain->assemblies, ass->name, ass);
631 // fixme: maybe this must be recursive ?
632 for (i = 0; (tmp = ass->image->references [i]) != NULL; i++) {
633 if (!g_hash_table_lookup (domain->assemblies, tmp->name))
634 g_hash_table_insert (domain->assemblies, tmp->name, tmp);
641 remove_assembly (gpointer key, gpointer value, gpointer user_data)
643 mono_assembly_close ((MonoAssembly *)value);
647 mono_domain_unload (MonoDomain *domain, gboolean force)
649 if ((domain == mono_root_domain) && !force) {
650 g_warning ("cant unload root domain");
654 g_hash_table_foreach (domain->assemblies, remove_assembly, NULL);
656 g_hash_table_destroy (domain->env);
657 g_hash_table_destroy (domain->assemblies);
658 mono_g_hash_table_destroy (domain->class_vtable_hash);
659 g_hash_table_destroy (domain->jit_code_hash);
660 mono_g_hash_table_destroy (domain->ldstr_table);
661 mono_jit_info_table_free (domain->jit_info_table);
662 mono_mempool_destroy (domain->mp);
664 // fixme: anything else required ? */
671 if ((domain == mono_root_domain))
672 mono_root_domain = NULL;
676 ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file,
677 MonoObject *evidence, MonoArray *args)
679 MonoDomain *cdom = mono_domain_get ();
680 MonoAssembly *assembly;
682 MonoCLIImageInfo *iinfo;
688 mono_domain_set (ad->data);
690 filename = mono_string_to_utf8 (file);
691 assembly = mono_assembly_open (filename, NULL, NULL);
695 mono_raise_exception ((MonoException *)mono_exception_from_name (
696 mono_defaults.corlib, "System.IO", "FileNotFoundException"));
699 image = assembly->image;
700 iinfo = image->image_info;
701 method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
704 g_error ("No entry point method found in %s", image->name);
706 margs = mono_domain_transfer_object (cdom, ad->data, (MonoObject *)args);
707 res = mono_runtime_exec_main (method, (MonoArray *)margs);
709 mono_domain_set (cdom);