Wed Aug 29 18:37:37 CEST 2007 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / image.c
index 72b1bb40ce1178f9fb3ab6e88d9e7072840a89cd..ecd8a81f5083af8e640f5512c3c183c8b6c76375 100644 (file)
 #include <mono/io-layer/io-layer.h>
 #include <mono/utils/mono-logger.h>
 #include <mono/utils/mono-path.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/assembly.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 
 #define INVALID_ADDRESS 0xffffffff
 
@@ -446,6 +450,11 @@ mono_image_check_for_module_cctor (MonoImage *image)
                image->checked_module_cctor = TRUE;
                return;
        }
+       if (image->dynamic) {
+               /* FIXME: */
+               image->checked_module_cctor = TRUE;
+               return;
+       }
        if (t->rows >= 1) {
                guint32 nameidx = mono_metadata_decode_row_col (t, 0, MONO_TYPEDEF_NAME);
                const char *name = mono_metadata_string_heap (image, nameidx);
@@ -570,12 +579,31 @@ build_guid_table (gboolean refonly)
        g_hash_table_foreach (loaded_images, register_guid, NULL);
 }
 
+static gpointer
+class_key_extract (gpointer value)
+{
+       MonoClass *class = value;
+
+       return GUINT_TO_POINTER (class->type_token);
+}
+
+static gpointer*
+class_next_value (gpointer value)
+{
+       MonoClass *class = value;
+
+       return (gpointer*)&class->next_class_cache;
+}
+
 void
 mono_image_init (MonoImage *image)
 {
        image->mempool = mono_mempool_new ();
        image->method_cache = g_hash_table_new (NULL, NULL);
-       image->class_cache = g_hash_table_new (NULL, NULL);
+       mono_internal_hash_table_init (&image->class_cache,
+                                      g_direct_hash,
+                                      class_key_extract,
+                                      class_next_value);
        image->field_cache = g_hash_table_new (NULL, NULL);
 
        image->delegate_begin_invoke_cache = 
@@ -1074,7 +1102,26 @@ mono_image_close (MonoImage *image)
                return;
 
        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading image %s [%p].", image->name, image);
-       
+
+       mono_metadata_clean_for_image (image);
+
+       /*
+        * The caches inside a MonoImage might refer to metadata which is stored in referenced 
+        * assemblies, so we can't release these references in mono_assembly_close () since the
+        * MonoImage might outlive its associated MonoAssembly.
+        */
+       if (image->references) {
+               int i;
+
+               for (i = 0; image->references [i]; i++) {
+                       if (image->references [i])
+                               mono_assembly_close (image->references [i]);
+               }
+
+               g_free (image->references);
+               image->references = NULL;
+       }
+
        mono_images_lock ();
        loaded_images = image->ref_only ? loaded_images_refonly_hash : loaded_images_hash;
        loaded_images_guid = image->ref_only ? loaded_images_refonly_guid_hash : loaded_images_guid_hash;
@@ -1125,7 +1172,7 @@ mono_image_close (MonoImage *image)
        }
 
        g_hash_table_destroy (image->method_cache);
-       g_hash_table_destroy (image->class_cache);
+       mono_internal_hash_table_destroy (&image->class_cache);
        g_hash_table_destroy (image->field_cache);
        if (image->array_cache) {
                g_hash_table_foreach (image->array_cache, free_array_cache_entry, NULL);
@@ -1186,6 +1233,8 @@ mono_image_close (MonoImage *image)
        }
        if (image->modules)
                g_free (image->modules);
+       if (image->modules_loaded)
+               g_free (image->modules_loaded);
        if (image->references)
                g_free (image->references);
        /*g_print ("destroy image %p (dynamic: %d)\n", image, image->dynamic);*/