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;
27 ldstr_hash (const char* str)
31 len = mono_metadata_decode_blob_size (str, &str);
35 * FIXME: The distribution may not be so nice with lots of
36 * null chars in the string.
38 for (str += 1; str < end; str++)
39 h = (h << 5) - h + *str;
44 ldstr_equal (const char *str1, const char *str2) {
46 len = mono_metadata_decode_blob_size (str1, NULL);
47 len2 = mono_metadata_decode_blob_size (str2, NULL);
50 return memcmp (str1, str2, len) == 0;
59 domain = GC_malloc (sizeof (MonoDomain));
61 domain = g_new0 (MonoDomain, 1);
63 domain->domain = NULL;
65 domain->friendly_name = NULL;
67 domain->mp = mono_mempool_new ();
68 domain->env = g_hash_table_new (g_str_hash, g_str_equal);
69 domain->assemblies = g_hash_table_new (g_str_hash, g_str_equal);
70 domain->class_vtable_hash = g_hash_table_new (NULL, NULL);
71 domain->jit_code_hash = g_hash_table_new (NULL, NULL);
72 domain->ldstr_table = g_hash_table_new ((GHashFunc)ldstr_hash, (GCompareFunc)ldstr_equal);
77 MonoDomain *mono_root_domain = NULL;
82 * Creates the initial application domain and initializes the mono_defaults
85 * Returns: the initial domain.
88 mono_init (const char *filename)
90 static MonoDomain *domain = NULL;
91 MonoAppDomainSetup *setup;
96 enum MonoImageOpenStatus status = MONO_IMAGE_OK;
99 g_assert_not_reached ();
101 appdomain_thread_id = TlsAlloc ();
103 domain = mono_create_domain ();
104 mono_root_domain = domain;
106 TlsSetValue (appdomain_thread_id, domain);
108 /* find the corlib */
109 ass = mono_assembly_open (CORLIB_NAME, NULL, &status);
110 if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
112 case MONO_IMAGE_ERROR_ERRNO:
113 g_print ("The assembly corlib.dll was not found or could not be loaded.\n");
114 g_print ("It should have been installed in the `%s' directory.\n", MONO_ASSEMBLIES);
117 case MONO_IMAGE_IMAGE_INVALID:
118 g_print ("The file %s/corlib.dll is an invalid CIL image", MONO_ASSEMBLIES);
124 mono_defaults.corlib = ass->image;
126 mono_defaults.object_class = mono_class_from_name (
127 mono_defaults.corlib, "System", "Object");
128 g_assert (mono_defaults.object_class != 0);
130 mono_defaults.void_class = mono_class_from_name (
131 mono_defaults.corlib, "System", "Void");
132 g_assert (mono_defaults.void_class != 0);
134 mono_defaults.boolean_class = mono_class_from_name (
135 mono_defaults.corlib, "System", "Boolean");
136 g_assert (mono_defaults.boolean_class != 0);
138 mono_defaults.byte_class = mono_class_from_name (
139 mono_defaults.corlib, "System", "Byte");
140 g_assert (mono_defaults.byte_class != 0);
142 mono_defaults.sbyte_class = mono_class_from_name (
143 mono_defaults.corlib, "System", "SByte");
144 g_assert (mono_defaults.sbyte_class != 0);
146 mono_defaults.int16_class = mono_class_from_name (
147 mono_defaults.corlib, "System", "Int16");
148 g_assert (mono_defaults.int16_class != 0);
150 mono_defaults.uint16_class = mono_class_from_name (
151 mono_defaults.corlib, "System", "UInt16");
152 g_assert (mono_defaults.uint16_class != 0);
154 mono_defaults.int32_class = mono_class_from_name (
155 mono_defaults.corlib, "System", "Int32");
156 g_assert (mono_defaults.int32_class != 0);
158 mono_defaults.uint32_class = mono_class_from_name (
159 mono_defaults.corlib, "System", "UInt32");
160 g_assert (mono_defaults.uint32_class != 0);
162 mono_defaults.uint_class = mono_class_from_name (
163 mono_defaults.corlib, "System", "UIntPtr");
164 g_assert (mono_defaults.uint_class != 0);
166 mono_defaults.int_class = mono_class_from_name (
167 mono_defaults.corlib, "System", "IntPtr");
168 g_assert (mono_defaults.int_class != 0);
170 mono_defaults.int64_class = mono_class_from_name (
171 mono_defaults.corlib, "System", "Int64");
172 g_assert (mono_defaults.int64_class != 0);
174 mono_defaults.uint64_class = mono_class_from_name (
175 mono_defaults.corlib, "System", "UInt64");
176 g_assert (mono_defaults.uint64_class != 0);
178 mono_defaults.single_class = mono_class_from_name (
179 mono_defaults.corlib, "System", "Single");
180 g_assert (mono_defaults.single_class != 0);
182 mono_defaults.double_class = mono_class_from_name (
183 mono_defaults.corlib, "System", "Double");
184 g_assert (mono_defaults.double_class != 0);
186 mono_defaults.char_class = mono_class_from_name (
187 mono_defaults.corlib, "System", "Char");
188 g_assert (mono_defaults.char_class != 0);
190 mono_defaults.string_class = mono_class_from_name (
191 mono_defaults.corlib, "System", "String");
192 g_assert (mono_defaults.string_class != 0);
194 mono_defaults.enum_class = mono_class_from_name (
195 mono_defaults.corlib, "System", "Enum");
196 g_assert (mono_defaults.enum_class != 0);
198 mono_defaults.array_class = mono_class_from_name (
199 mono_defaults.corlib, "System", "Array");
200 g_assert (mono_defaults.array_class != 0);
202 mono_defaults.delegate_class = mono_class_from_name (
203 mono_defaults.corlib, "System", "Delegate");
204 g_assert (mono_defaults.delegate_class != 0);
206 mono_defaults.typehandle_class = mono_class_from_name (
207 mono_defaults.corlib, "System", "RuntimeTypeHandle");
208 g_assert (mono_defaults.typehandle_class != 0);
210 mono_defaults.methodhandle_class = mono_class_from_name (
211 mono_defaults.corlib, "System", "RuntimeMethodHandle");
212 g_assert (mono_defaults.methodhandle_class != 0);
214 mono_defaults.fieldhandle_class = mono_class_from_name (
215 mono_defaults.corlib, "System", "RuntimeFieldHandle");
216 g_assert (mono_defaults.fieldhandle_class != 0);
218 mono_defaults.monotype_class = mono_class_from_name (
219 mono_defaults.corlib, "System", "MonoType");
220 g_assert (mono_defaults.monotype_class != 0);
222 mono_defaults.exception_class = mono_class_from_name (
223 mono_defaults.corlib, "System", "Exception");
224 g_assert (mono_defaults.exception_class != 0);
227 class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
228 setup = (MonoAppDomainSetup *) mono_object_new (domain, class);
229 ves_icall_System_AppDomainSetup_InitAppDomainSetup (setup);
231 name = mono_string_new (domain, g_path_get_basename (filename));
233 class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
234 ad = (MonoAppDomain *) mono_object_new (domain, class);
237 domain->setup = setup;
238 domain->friendly_name = name;
244 ves_icall_System_AppDomainSetup_InitAppDomainSetup (MonoAppDomainSetup *setup)
246 // fixme: implement me
250 * mono_domain_transfer_object:
251 * @src: the source domain
252 * @dst: the destination domain
253 * @obj: the object to transfer
255 * This function is used to transfer objects between domains. This is done by
256 * marshalling or serialisation.
259 mono_domain_transfer_object (MonoDomain *src, MonoDomain *dst, MonoObject *obj)
267 g_assert (obj->vtable->domain == src);
269 /* fixme: transfer an object from one domain into another */
271 klass = obj->vtable->klass;
273 if (MONO_CLASS_IS_ARRAY (klass)) {
274 MonoArray *ao = (MonoArray *)obj;
275 int esize, ecount, i;
278 sizes = alloca (klass->rank * sizeof(guint32) * 2);
279 esize = mono_array_element_size (klass);
281 for (i = 0; i < klass->rank; ++i) {
282 sizes [i] = ao->bounds [i].length;
283 ecount *= ao->bounds [i].length;
284 sizes [i + klass->rank] = ao->bounds [i].lower_bound;
286 res = (MonoObject *)mono_array_new_full (dst, klass, sizes, sizes + klass->rank);
287 if (klass->element_class->valuetype) {
288 memcpy (res, (char *)ao + sizeof(MonoArray), esize * ecount);
290 g_assert (esize == sizeof (gpointer));
291 for (i = 0; i < ecount; i++) {
292 int offset = sizeof (MonoArray) + esize * i;
293 gpointer *src_ea = (gpointer *)((char *)ao + offset);
294 gpointer *dst_ea = (gpointer *)((char *)res + offset);
296 *dst_ea = mono_domain_transfer_object (src, dst, *src_ea);
299 } else if (klass == mono_defaults.string_class) {
300 MonoString *str = (MonoString *)obj;
301 res = (MonoObject *)mono_string_new_utf16 (dst,
302 (const guint16 *)str->c_str->vector, str->length);
304 // fixme: we need generic marshalling code here */
305 g_assert_not_reached ();
312 ves_icall_System_AppDomain_GetData (MonoAppDomain *ad, MonoString *name)
314 MonoDomain *add = ad->data;
315 MonoDomain *cur = mono_domain_get ();
319 g_assert (ad != NULL);
320 g_assert (name != NULL);
322 str = mono_string_to_utf8 (name);
324 if (!strcmp (str, "APPBASE"))
325 o = (MonoObject *)add->setup->application_base;
326 else if (!strcmp (str, "APP_CONFIG_FILE"))
327 o = (MonoObject *)add->setup->configuration_file;
328 else if (!strcmp (str, "DYNAMIC_BASE"))
329 o = (MonoObject *)add->setup->dynamic_base;
330 else if (!strcmp (str, "APP_NAME"))
331 o = (MonoObject *)add->setup->application_name;
332 else if (!strcmp (str, "CACHE_BASE"))
333 o = (MonoObject *)add->setup->cache_path;
334 else if (!strcmp (str, "PRIVATE_BINPATH"))
335 o = (MonoObject *)add->setup->private_bin_path;
336 else if (!strcmp (str, "BINPATH_PROBE_ONLY"))
337 o = (MonoObject *)add->setup->private_bin_path_probe;
338 else if (!strcmp (str, "SHADOW_COPY_DIRS"))
339 o = (MonoObject *)add->setup->shadow_copy_directories;
340 else if (!strcmp (str, "FORCE_CACHE_INSTALL"))
341 o = (MonoObject *)add->setup->shadow_copy_files;
343 o = g_hash_table_lookup (add->env, str);
350 return mono_domain_transfer_object (add, cur, o);
354 ves_icall_System_AppDomain_SetData (MonoAppDomain *ad, MonoString *name, MonoObject *data)
356 MonoDomain *add = ad->data;
357 MonoDomain *cur = mono_domain_get ();
361 g_assert (ad != NULL);
362 g_assert (name != NULL);
364 o = mono_domain_transfer_object (cur, add, data);
366 /* fixme: need a hash func for MonoString */
367 str = mono_string_to_utf8 (name);
368 g_hash_table_insert (add->env, str, o);
373 ves_icall_System_AppDomain_getSetup (MonoAppDomain *ad)
375 g_assert (ad != NULL);
376 g_assert (ad->data != NULL);
378 return ad->data->setup;
382 ves_icall_System_AppDomain_getFriendlyName (MonoAppDomain *ad)
384 g_assert (ad != NULL);
385 g_assert (ad->data != NULL);
387 return ad->data->friendly_name;
393 * Returns the current domain.
398 return ((MonoDomain *)TlsGetValue (appdomain_thread_id));
403 * @domain: the new domain
405 * Sets the current domain to @domain.
408 mono_domain_set (MonoDomain *domain)
410 TlsSetValue (appdomain_thread_id, domain);
414 ves_icall_System_AppDomain_getCurDomain ()
416 MonoDomain *add = mono_domain_get ();
421 ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomainSetup *setup)
423 MonoDomain *domain = mono_domain_get ();
428 adclass = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
430 // fixme: pin all those objects
431 ad = (MonoAppDomain *) mono_object_new (domain, adclass);
432 ad->data = data = mono_create_domain ();
435 data->friendly_name = friendly_name;
437 // fixme: what to do next ?
446 } add_assembly_helper_t;
449 add_assembly (gpointer key, gpointer value, gpointer user_data)
451 add_assembly_helper_t *ah = (add_assembly_helper_t *) user_data;
453 mono_array_set (ah->res, gpointer, ah->idx++, mono_assembly_get_object (ah->domain, value));
457 ves_icall_System_AppDomain_GetAssemblies (MonoAppDomain *ad)
459 MonoDomain *domain = ad->data;
460 static MonoClass *System_Reflection_Assembly;
462 add_assembly_helper_t ah;
464 if (!System_Reflection_Assembly)
465 System_Reflection_Assembly = mono_class_from_name (
466 mono_defaults.corlib, "System.Reflection", "Assembly");
468 res = mono_array_new (domain, System_Reflection_Assembly, g_hash_table_size (domain->assemblies));
473 g_hash_table_foreach (domain->assemblies, add_assembly, &ah);
479 MonoReflectionAssembly *
480 ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad, MonoReflectionAssemblyName *assRef, MonoObject *evidence)
482 MonoDomain *domain = ad->data;
483 char *name, *filename;
484 enum MonoImageOpenStatus status = MONO_IMAGE_OK;
487 /* FIXME : examine evidence? */
489 g_assert (assRef != NULL);
490 g_assert (assRef->name != NULL);
492 /* FIXME : examine version, culture info */
494 name = filename = mono_string_to_utf8 (assRef->name);
496 if (strncmp (filename, "file://", 7) == 0)
499 ass = mono_assembly_open (filename, NULL, &status);
504 mono_raise_exception ((MonoException *)mono_exception_from_name (mono_defaults.corlib, "System.IO", "FileNotFoundException"));
506 return mono_assembly_get_object (domain, ass);
510 ves_icall_System_AppDomain_Unload (MonoAppDomain *ad)
512 mono_domain_unload (ad->data, FALSE);
516 * mono_domain_assembly_open:
517 * @domain: the application domain
518 * @name: file name of the assembly
520 * fixme: maybe we should integrate this with mono_assembly_open ??
523 mono_domain_assembly_open (MonoDomain *domain, char *name)
525 MonoAssembly *ass, *tmp;
528 if ((ass = g_hash_table_lookup (domain->assemblies, name)))
531 if (!(ass = mono_assembly_open (name, NULL, NULL)))
534 g_hash_table_insert (domain->assemblies, ass->name, ass);
536 // fixme: maybe this must be recursive ?
537 for (i = 0; (tmp = ass->image->references [i]) != NULL; i++) {
538 if (!g_hash_table_lookup (domain->assemblies, tmp->name))
539 g_hash_table_insert (domain->assemblies, tmp->name, tmp);
546 remove_assembly (gpointer key, gpointer value, gpointer user_data)
548 mono_assembly_close ((MonoAssembly *)value);
552 mono_domain_unload (MonoDomain *domain, gboolean force)
554 if ((domain == mono_root_domain) && !force) {
555 g_warning ("cant unload root domain");
559 g_hash_table_foreach (domain->assemblies, remove_assembly, NULL);
561 g_hash_table_destroy (domain->env);
562 g_hash_table_destroy (domain->assemblies);
563 g_hash_table_destroy (domain->class_vtable_hash);
564 g_hash_table_destroy (domain->jit_code_hash);
565 g_hash_table_destroy (domain->ldstr_table);
566 mono_mempool_destroy (domain->mp);
568 // fixme: anything else required ? */
575 if ((domain == mono_root_domain))
576 mono_root_domain = NULL;
580 ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file,
581 MonoObject *evidence, MonoArray *args)
583 MonoDomain *cdom = mono_domain_get ();
584 MonoAssembly *assembly;
586 MonoCLIImageInfo *iinfo;
592 mono_domain_set (ad->data);
594 filename = mono_string_to_utf8 (file);
595 assembly = mono_assembly_open (filename, NULL, NULL);
599 mono_raise_exception ((MonoException *)mono_exception_from_name (
600 mono_defaults.corlib, "System.IO", "FileNotFoundException"));
603 image = assembly->image;
604 iinfo = image->image_info;
605 method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
608 g_error ("No entry point method found in %s", image->name);
610 margs = mono_domain_transfer_object (cdom, ad->data, (MonoObject *)args);
611 res = mono_runtime_exec_main (method, (MonoArray *)margs);
613 mono_domain_set (cdom);