Make nested type loading lazier.
[mono.git] / mono / metadata / image.c
index 53327041559cfb48eabd4b86173c1ecb657f5594..f054be8acca0621cc168f399aeefa6e1468d354a 100644 (file)
@@ -27,7 +27,7 @@
 #include "marshal.h"
 #include "coree.h"
 #include <mono/io-layer/io-layer.h>
-#include <mono/utils/mono-logger.h>
+#include <mono/utils/mono-logger-internal.h>
 #include <mono/utils/mono-path.h>
 #include <mono/utils/mono-mmap.h>
 #include <mono/utils/mono-io-portability.h>
@@ -36,6 +36,7 @@
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/security-core-clr.h>
 #include <mono/metadata/verify-internals.h>
+#include <mono/metadata/verify.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #ifdef HAVE_UNISTD_H
@@ -57,6 +58,39 @@ static gboolean debug_assembly_unload = FALSE;
 static gboolean mutex_inited;
 static CRITICAL_SECTION images_mutex;
 
+typedef struct ImageUnloadHook ImageUnloadHook;
+struct ImageUnloadHook {
+       ImageUnloadHook *next;
+       MonoImageUnloadFunc func;
+       gpointer user_data;
+};
+
+ImageUnloadHook *image_unload_hook = NULL;
+
+void
+mono_install_image_unload_hook (MonoImageUnloadFunc func, gpointer user_data)
+{
+       ImageUnloadHook *hook;
+       
+       g_return_if_fail (func != NULL);
+
+       hook = g_new0 (ImageUnloadHook, 1);
+       hook->func = func;
+       hook->user_data = user_data;
+       hook->next = image_unload_hook;
+       image_unload_hook = hook;
+}
+
+static void
+mono_image_invoke_unload_hook (MonoImage *image)
+{
+       ImageUnloadHook *hook;
+
+       for (hook = image_unload_hook; hook; hook = hook->next) {
+               hook->func (image, hook->user_data);
+       }
+}
+
 /* returns offset relative to image->raw_data */
 guint32
 mono_cli_rva_image_map (MonoImage *image, guint32 addr)
@@ -469,10 +503,6 @@ mono_image_check_for_module_cctor (MonoImage *image)
        MonoTableInfo *t, *mt;
        t = &image->tables [MONO_TABLE_TYPEDEF];
        mt = &image->tables [MONO_TABLE_METHOD];
-       if (mono_framework_version () == 1) {
-               image->checked_module_cctor = TRUE;
-               return;
-       }
        if (image->dynamic) {
                /* FIXME: */
                image->checked_module_cctor = TRUE;
@@ -534,7 +564,7 @@ mono_image_load_module (MonoImage *image, int idx)
        GList *list_iter, *valid_modules = NULL;
        MonoImageOpenStatus status;
 
-       if ((image->module_count == 0) || (idx > image->module_count))
+       if ((image->module_count == 0) || (idx > image->module_count || idx <= 0))
                return NULL;
        if (image->modules_loaded [idx - 1])
                return image->modules [idx - 1];
@@ -881,6 +911,7 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
 {
        MonoCLIImageInfo *iinfo;
        MonoDotNetHeader *header;
+       GSList *errors = NULL;
 
        mono_profiler_module_event (image, MONO_PROFILE_START_LOAD);
 
@@ -895,7 +926,7 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
        if (care_about_pecoff == FALSE)
                goto done;
 
-       if (!mono_verifier_verify_pe_data (image, NULL))
+       if (!mono_verifier_verify_pe_data (image, &errors))
                goto invalid_image;
 
        if (!mono_image_load_pe_data (image))
@@ -905,13 +936,13 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
                goto done;
        }
 
-       if (!mono_verifier_verify_cli_data (image, NULL))
+       if (!mono_verifier_verify_cli_data (image, &errors))
                goto invalid_image;
 
        if (!mono_image_load_cli_data (image))
                goto invalid_image;
 
-       if (!mono_verifier_verify_table_data (image, NULL))
+       if (!mono_verifier_verify_table_data (image, &errors))
                goto invalid_image;
 
        mono_image_load_names (image);
@@ -926,9 +957,14 @@ done:
        return image;
 
 invalid_image:
+       if (errors) {
+               MonoVerifyInfo *info = errors->data;
+               g_warning ("Could not load image %s due to %s", image->name, info->message);
+               mono_free_verify_list (errors);
+       }
        mono_profiler_module_loaded (image, MONO_PROFILE_FAILED);
        mono_image_close (image);
-               return NULL;
+       return NULL;
 }
 
 static MonoImage *
@@ -1417,6 +1453,7 @@ mono_image_close_except_pools (MonoImage *image)
        MonoImage *image2;
        GHashTable *loaded_images;
        int i;
+       GSList *free_list;
 
        g_return_val_if_fail (image != NULL, FALSE);
 
@@ -1459,7 +1496,9 @@ mono_image_close_except_pools (MonoImage *image)
 
        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading image %s [%p].", image->name, image);
 
-       mono_metadata_clean_for_image (image);
+       mono_image_invoke_unload_hook (image);
+
+       free_list = mono_metadata_clean_for_image (image);
 
        /*
         * The caches inside a MonoImage might refer to metadata which is stored in referenced 
@@ -1572,9 +1611,6 @@ mono_image_close_except_pools (MonoImage *image)
        g_hash_table_destroy (image->helper_signatures);
        g_hash_table_destroy (image->method_signatures);
 
-       if (image->generic_class_cache)
-               g_hash_table_destroy (image->generic_class_cache);
-
        if (image->rgctx_template_hash)
                g_hash_table_destroy (image->rgctx_template_hash);
 
@@ -1582,6 +1618,7 @@ mono_image_close_except_pools (MonoImage *image)
                mono_property_hash_destroy (image->property_hash);
 
        g_slist_free (image->reflection_info_unregister_classes);
+       image->reflection_info_unregister_classes = free_list;
 
        if (image->interface_bitset) {
                mono_unload_interface_ids (image->interface_bitset);
@@ -1625,6 +1662,12 @@ void
 mono_image_close_finish (MonoImage *image)
 {
        int i;
+       GSList *l;
+
+       for (l = image->reflection_info_unregister_classes; l; l = l->next)
+               g_free (l->data);
+       g_slist_free (image->reflection_info_unregister_classes);
+       image->reflection_info_unregister_classes = NULL;
 
        if (image->references && !image->dynamic) {
                MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLYREF];