2002-07-15 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / metadata / domain.c
1
2 /*
3  * domain.c: MonoDomain functions
4  *
5  * Author:
6  *      Dietmar Maurer (dietmar@ximian.com)
7  *
8  * (C) 2001 Ximian, Inc.
9  */
10
11 #include <config.h>
12 #include <glib.h>
13 #include <string.h>
14
15 #if HAVE_BOEHM_GC
16 #include <gc/gc.h>
17 #endif
18
19 #include <mono/metadata/object.h>
20 #include <mono/metadata/appdomain.h>
21 #include <mono/metadata/assembly.h>
22 #include <mono/metadata/exception.h>
23 #include <mono/metadata/cil-coff.h>
24
25 static guint32 appdomain_thread_id = 0;
26
27 MonoDomain *mono_root_domain = NULL;
28
29 static MonoJitInfoTable *
30 mono_jit_info_table_new (void)
31 {
32         return g_array_new (FALSE, FALSE, sizeof (gpointer));
33 }
34
35 static void
36 mono_jit_info_table_free (MonoJitInfoTable *table)
37 {
38         g_array_free (table, TRUE);
39 }
40
41 static int
42 mono_jit_info_table_index (MonoJitInfoTable *table, char *addr)
43 {
44         int left = 0, right = table->len;
45
46         while (left < right) {
47                 int pos = (left + right) / 2;
48                 MonoJitInfo *ji = g_array_index (table, gpointer, pos);
49                 char *start = ji->code_start;
50                 char *end = start + ji->code_size;
51
52                 if (addr < start)
53                         right = pos;
54                 else if (addr >= end) 
55                         left = pos + 1;
56                 else
57                         return pos;
58         }
59
60         return left;
61 }
62
63 MonoJitInfo *
64 mono_jit_info_table_find (MonoDomain *domain, char *addr)
65 {
66         MonoJitInfoTable *table = domain->jit_info_table;
67         int left = 0, right = table->len;
68
69         while (left < right) {
70                 int pos = (left + right) / 2;
71                 MonoJitInfo *ji = g_array_index (table, gpointer, pos);
72                 char *start = ji->code_start;
73                 char *end = start + ji->code_size;
74
75                 if (addr < start)
76                         right = pos;
77                 else if (addr >= end) 
78                         left = pos + 1;
79                 else
80                         return ji;
81         }
82
83         /* maybe irt is shared code, so we also search in the root domain */
84         if (domain != mono_root_domain)
85                 return mono_jit_info_table_find (mono_root_domain, addr);
86
87         return NULL;
88 }
89
90 void
91 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
92 {
93         MonoJitInfoTable *table = domain->jit_info_table;
94         gpointer start = ji->code_start;
95         int pos = mono_jit_info_table_index (table, start);
96
97         g_array_insert_val (table, pos, ji);
98 }
99
100 static int
101 ldstr_hash (const char* str)
102 {
103         guint len, h;
104         const char *end;
105         len = mono_metadata_decode_blob_size (str, &str) - 1;
106         end = str + len;
107         /* if len == 0 *str will point to the mark byte */
108         h = len? *str: 0;
109         /*
110          * FIXME: The distribution may not be so nice with lots of
111          * null chars in the string.
112          */
113         for (str += 1; str < end; str++)
114                 h = (h << 5) - h + *str;
115         return h;
116 }
117
118 static gboolean
119 ldstr_equal (const char *str1, const char *str2) {
120         int len, len2;
121         len = mono_metadata_decode_blob_size (str1, NULL) - 1;
122         len2 = mono_metadata_decode_blob_size (str2, NULL) - 1;
123         if (len != len2)
124                 return 0;
125         return memcmp (str1, str2, len) == 0;
126 }
127
128 #if HAVE_BOEHM_GC
129 static void
130 domain_finalizer (void *obj, void *data) {
131         g_print ("domain finalized\n");
132 }
133 #endif
134
135 MonoDomain *
136 mono_domain_create (void)
137 {
138         MonoDomain *domain;
139
140 #if HAVE_BOEHM_GC
141         domain = GC_malloc (sizeof (MonoDomain));
142         GC_register_finalizer (domain, domain_finalizer, NULL, NULL, NULL);
143 #else
144         domain = g_new0 (MonoDomain, 1);
145 #endif
146         domain->domain = NULL;
147         domain->setup = NULL;
148         domain->friendly_name = NULL;
149
150         domain->mp = mono_mempool_new ();
151         domain->env = g_hash_table_new (g_str_hash, g_str_equal);
152         domain->assemblies = g_hash_table_new (g_str_hash, g_str_equal);
153         domain->class_vtable_hash = mono_g_hash_table_new (NULL, NULL);
154         domain->proxy_vtable_hash = mono_g_hash_table_new (NULL, NULL);
155         domain->static_data_hash = mono_g_hash_table_new (NULL, NULL);
156         domain->jit_code_hash = g_hash_table_new (NULL, NULL);
157         domain->ldstr_table = mono_g_hash_table_new ((GHashFunc)ldstr_hash, (GCompareFunc)ldstr_equal);
158         domain->jit_info_table = mono_jit_info_table_new ();
159
160         InitializeCriticalSection (&domain->lock);
161         return domain;
162 }
163
164 /**
165  * mono_init:
166  * 
167  * Creates the initial application domain and initializes the mono_defaults
168  * structure.
169  * This function is guaranteed to not run any IL code.
170  *
171  * Returns: the initial domain.
172  */
173 MonoDomain *
174 mono_init (const char *filename)
175 {
176         static MonoDomain *domain = NULL;
177         MonoAssembly *ass;
178         MonoImageOpenStatus status = MONO_IMAGE_OK;
179         MonoAssemblyName corlib_aname;
180
181         if (domain)
182                 g_assert_not_reached ();
183
184         appdomain_thread_id = TlsAlloc ();
185
186         domain = mono_domain_create ();
187         mono_root_domain = domain;
188
189         TlsSetValue (appdomain_thread_id, domain);
190
191         /* find the corlib */
192         corlib_aname.name = "corlib";
193         ass = mono_assembly_load (&corlib_aname, NULL, &status);
194         if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
195                 switch (status){
196                 case MONO_IMAGE_ERROR_ERRNO:
197                         g_print ("The assembly corlib.dll was not found or could not be loaded.\n");
198                         g_print ("It should have been installed in the `%s' directory.\n", MONO_ASSEMBLIES);
199                         break;
200                 case MONO_IMAGE_IMAGE_INVALID:
201                         g_print ("The file %s/corlib.dll is an invalid CIL image\n", MONO_ASSEMBLIES);
202                         break;
203                 case MONO_IMAGE_MISSING_ASSEMBLYREF:
204                         g_print ("Minning assembly reference in %s/corlib.dll\n", MONO_ASSEMBLIES);
205                         break;
206                 case MONO_IMAGE_OK:
207                         /* to suppress compiler warning */
208                         break;
209                 }
210                 
211                 exit (1);
212         }
213         mono_defaults.corlib = ass->image;
214
215         mono_defaults.object_class = mono_class_from_name (
216                 mono_defaults.corlib, "System", "Object");
217         g_assert (mono_defaults.object_class != 0);
218
219         mono_defaults.void_class = mono_class_from_name (
220                 mono_defaults.corlib, "System", "Void");
221         g_assert (mono_defaults.void_class != 0);
222
223         mono_defaults.boolean_class = mono_class_from_name (
224                 mono_defaults.corlib, "System", "Boolean");
225         g_assert (mono_defaults.boolean_class != 0);
226
227         mono_defaults.byte_class = mono_class_from_name (
228                 mono_defaults.corlib, "System", "Byte");
229         g_assert (mono_defaults.byte_class != 0);
230
231         mono_defaults.sbyte_class = mono_class_from_name (
232                 mono_defaults.corlib, "System", "SByte");
233         g_assert (mono_defaults.sbyte_class != 0);
234
235         mono_defaults.int16_class = mono_class_from_name (
236                 mono_defaults.corlib, "System", "Int16");
237         g_assert (mono_defaults.int16_class != 0);
238
239         mono_defaults.uint16_class = mono_class_from_name (
240                 mono_defaults.corlib, "System", "UInt16");
241         g_assert (mono_defaults.uint16_class != 0);
242
243         mono_defaults.int32_class = mono_class_from_name (
244                 mono_defaults.corlib, "System", "Int32");
245         g_assert (mono_defaults.int32_class != 0);
246
247         mono_defaults.uint32_class = mono_class_from_name (
248                 mono_defaults.corlib, "System", "UInt32");
249         g_assert (mono_defaults.uint32_class != 0);
250
251         mono_defaults.uint_class = mono_class_from_name (
252                 mono_defaults.corlib, "System", "UIntPtr");
253         g_assert (mono_defaults.uint_class != 0);
254
255         mono_defaults.int_class = mono_class_from_name (
256                 mono_defaults.corlib, "System", "IntPtr");
257         g_assert (mono_defaults.int_class != 0);
258
259         mono_defaults.int64_class = mono_class_from_name (
260                 mono_defaults.corlib, "System", "Int64");
261         g_assert (mono_defaults.int64_class != 0);
262
263         mono_defaults.uint64_class = mono_class_from_name (
264                 mono_defaults.corlib, "System", "UInt64");
265         g_assert (mono_defaults.uint64_class != 0);
266
267         mono_defaults.single_class = mono_class_from_name (
268                 mono_defaults.corlib, "System", "Single");
269         g_assert (mono_defaults.single_class != 0);
270
271         mono_defaults.double_class = mono_class_from_name (
272                 mono_defaults.corlib, "System", "Double");
273         g_assert (mono_defaults.double_class != 0);
274
275         mono_defaults.char_class = mono_class_from_name (
276                 mono_defaults.corlib, "System", "Char");
277         g_assert (mono_defaults.char_class != 0);
278
279         mono_defaults.string_class = mono_class_from_name (
280                 mono_defaults.corlib, "System", "String");
281         g_assert (mono_defaults.string_class != 0);
282
283         mono_defaults.enum_class = mono_class_from_name (
284                 mono_defaults.corlib, "System", "Enum");
285         g_assert (mono_defaults.enum_class != 0);
286
287         mono_defaults.array_class = mono_class_from_name (
288                 mono_defaults.corlib, "System", "Array");
289         g_assert (mono_defaults.array_class != 0);
290
291         mono_defaults.multicastdelegate_class = mono_class_from_name (
292                 mono_defaults.corlib, "System", "MulticastDelegate");
293         g_assert (mono_defaults.multicastdelegate_class != 0 );
294
295         mono_defaults.asyncresult_class = mono_class_from_name (
296                 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", 
297                 "AsyncResult");
298         g_assert (mono_defaults.asyncresult_class != 0 );
299
300         mono_defaults.waithandle_class = mono_class_from_name (
301                 mono_defaults.corlib, "System.Threading", "WaitHandle");
302         g_assert (mono_defaults.waithandle_class != 0 );
303
304         mono_defaults.typehandle_class = mono_class_from_name (
305                 mono_defaults.corlib, "System", "RuntimeTypeHandle");
306         g_assert (mono_defaults.typehandle_class != 0);
307
308         mono_defaults.methodhandle_class = mono_class_from_name (
309                 mono_defaults.corlib, "System", "RuntimeMethodHandle");
310         g_assert (mono_defaults.methodhandle_class != 0);
311
312         mono_defaults.fieldhandle_class = mono_class_from_name (
313                 mono_defaults.corlib, "System", "RuntimeFieldHandle");
314         g_assert (mono_defaults.fieldhandle_class != 0);
315
316         mono_defaults.monotype_class = mono_class_from_name (
317                 mono_defaults.corlib, "System", "MonoType");
318         g_assert (mono_defaults.monotype_class != 0);
319
320         mono_defaults.exception_class = mono_class_from_name (
321                 mono_defaults.corlib, "System", "Exception");
322         g_assert (mono_defaults.exception_class != 0);
323
324         mono_defaults.thread_class = mono_class_from_name (
325                 mono_defaults.corlib, "System.Threading", "Thread");
326         g_assert (mono_defaults.thread_class != 0);
327
328         mono_defaults.appdomain_class = mono_class_from_name (
329                 mono_defaults.corlib, "System", "AppDomain");
330         g_assert (mono_defaults.appdomain_class != 0);
331
332         mono_defaults.transparent_proxy_class = mono_class_from_name (
333                 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
334         g_assert (mono_defaults.transparent_proxy_class != 0);
335
336         mono_defaults.real_proxy_class = mono_class_from_name (
337                 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
338         g_assert (mono_defaults.real_proxy_class != 0);
339
340         mono_defaults.mono_method_message_class = mono_class_from_name (
341                 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
342         g_assert (mono_defaults.mono_method_message_class != 0);
343
344         mono_defaults.field_info_class = mono_class_from_name (
345                 mono_defaults.corlib, "System.Reflection", "FieldInfo");
346         g_assert (mono_defaults.field_info_class != 0);
347
348         mono_defaults.stringbuilder_class = mono_class_from_name (
349                 mono_defaults.corlib, "System.Text", "StringBuilder");
350         g_assert (mono_defaults.stringbuilder_class != 0);
351
352         mono_defaults.math_class = mono_class_from_name (
353                 mono_defaults.corlib, "System", "Math");
354         g_assert (mono_defaults.math_class != 0);
355
356         mono_defaults.stack_frame_class = mono_class_from_name (
357                 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
358         g_assert (mono_defaults.stack_frame_class != 0);
359
360         mono_defaults.stack_trace_class = mono_class_from_name (
361                 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
362         g_assert (mono_defaults.stack_trace_class != 0);
363
364         mono_defaults.marshal_class = mono_class_from_name (
365                 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
366         g_assert (mono_defaults.marshal_class != 0);
367
368         domain->friendly_name = g_path_get_basename (filename);
369
370         return domain;
371 }
372
373 /**
374  * mono_domain_get:
375  *
376  * Returns the current domain.
377  */
378 inline MonoDomain *
379 mono_domain_get ()
380 {
381         return ((MonoDomain *)TlsGetValue (appdomain_thread_id));
382 }
383
384 /**
385  * mono_domain_set:
386  * @domain: the new domain
387  *
388  * Sets the current domain to @domain.
389  */
390 inline void
391 mono_domain_set (MonoDomain *domain)
392 {
393         TlsSetValue (appdomain_thread_id, domain);
394 }
395
396 /**
397  * mono_domain_assembly_open:
398  * @domain: the application domain
399  * @name: file name of the assembly
400  *
401  * fixme: maybe we should integrate this with mono_assembly_open ??
402  */
403 MonoAssembly *
404 mono_domain_assembly_open (MonoDomain *domain, char *name)
405 {
406         MonoAssembly *ass, *tmp;
407         int i;
408
409         if ((ass = g_hash_table_lookup (domain->assemblies, name)))
410                 return ass;
411
412         if (!(ass = mono_assembly_open (name, NULL)))
413                 return NULL;
414
415         mono_domain_lock (domain);
416         g_hash_table_insert (domain->assemblies, ass->aname.name, ass);
417         mono_domain_unlock (domain);
418
419         /* FIXME: maybe this must be recursive ? */
420         for (i = 0; (tmp = ass->image->references [i]) != NULL; i++) {
421                 if (!g_hash_table_lookup (domain->assemblies, tmp->aname.name))
422                         g_hash_table_insert (domain->assemblies, tmp->aname.name, tmp);
423         }
424
425         return ass;
426 }
427
428 static void
429 remove_assembly (gpointer key, gpointer value, gpointer user_data)
430 {
431         mono_assembly_close ((MonoAssembly *)value);
432 }
433
434 void
435 mono_domain_unload (MonoDomain *domain, gboolean force)
436 {
437         if ((domain == mono_root_domain) && !force) {
438                 g_warning ("cant unload root domain");
439                 return;
440         }
441
442         g_free (domain->friendly_name);
443         g_hash_table_foreach (domain->assemblies, remove_assembly, NULL);
444
445         g_hash_table_destroy (domain->env);
446         g_hash_table_destroy (domain->assemblies);
447         mono_g_hash_table_destroy (domain->class_vtable_hash);
448         mono_g_hash_table_destroy (domain->proxy_vtable_hash);
449         mono_g_hash_table_destroy (domain->static_data_hash);
450         g_hash_table_destroy (domain->jit_code_hash);
451         mono_g_hash_table_destroy (domain->ldstr_table);
452         mono_jit_info_table_free (domain->jit_info_table);
453         mono_mempool_destroy (domain->mp);
454         DeleteCriticalSection (&domain->lock);
455         
456         /* FIXME: anything else required ? */
457
458 #if HAVE_BOEHM_GC
459 #else
460         g_free (domain);
461 #endif
462
463         if ((domain == mono_root_domain))
464                 mono_root_domain = NULL;
465 }
466