Merge pull request #819 from brendanzagaeski/patch-1
[mono.git] / mono / metadata / image.c
index f054be8acca0621cc168f399aeefa6e1468d354a..dcb5c399a62edab973fd29eba6650b7071ab56ba 100644 (file)
@@ -31,6 +31,7 @@
 #include <mono/utils/mono-path.h>
 #include <mono/utils/mono-mmap.h>
 #include <mono/utils/mono-io-portability.h>
+#include <mono/utils/atomic.h>
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/object-internals.h>
@@ -60,12 +61,11 @@ static CRITICAL_SECTION images_mutex;
 
 typedef struct ImageUnloadHook ImageUnloadHook;
 struct ImageUnloadHook {
-       ImageUnloadHook *next;
        MonoImageUnloadFunc func;
        gpointer user_data;
 };
 
-ImageUnloadHook *image_unload_hook = NULL;
+GSList *image_unload_hooks;
 
 void
 mono_install_image_unload_hook (MonoImageUnloadFunc func, gpointer user_data)
@@ -77,16 +77,35 @@ mono_install_image_unload_hook (MonoImageUnloadFunc func, gpointer user_data)
        hook = g_new0 (ImageUnloadHook, 1);
        hook->func = func;
        hook->user_data = user_data;
-       hook->next = image_unload_hook;
-       image_unload_hook = hook;
+       image_unload_hooks = g_slist_prepend (image_unload_hooks, hook);
+}
+
+void
+mono_remove_image_unload_hook (MonoImageUnloadFunc func, gpointer user_data)
+{
+       GSList *l;
+       ImageUnloadHook *hook;
+
+       for (l = image_unload_hooks; l; l = l->next) {
+               hook = l->data;
+
+               if (hook->func == func && hook->user_data == user_data) {
+                       g_free (hook);
+                       image_unload_hooks = g_slist_delete_link (image_unload_hooks, l);
+                       break;
+               }
+       }
 }
 
 static void
 mono_image_invoke_unload_hook (MonoImage *image)
 {
+       GSList *l;
        ImageUnloadHook *hook;
 
-       for (hook = image_unload_hook; hook; hook = hook->next) {
+       for (l = image_unload_hooks; l; l = l->next) {
+               hook = l->data;
+
                hook->func (image, hook->user_data);
        }
 }
@@ -132,7 +151,16 @@ mono_image_rva_map (MonoImage *image, guint32 addr)
        const int top = iinfo->cli_section_count;
        MonoSectionTable *tables = iinfo->cli_section_tables;
        int i;
-       
+
+#ifdef HOST_WIN32
+       if (image->is_module_handle) {
+               if (addr && addr < image->raw_data_len)
+                       return image->raw_data + addr;
+               else
+                       return NULL;
+       }
+#endif
+
        for (i = 0; i < top; i++){
                if ((addr >= tables->st_virtual_address) &&
                    (addr < tables->st_virtual_address + tables->st_raw_data_size)){
@@ -140,10 +168,6 @@ mono_image_rva_map (MonoImage *image, guint32 addr)
                                if (!mono_image_ensure_section_idx (image, i))
                                        return NULL;
                        }
-#ifdef HOST_WIN32
-                       if (image->is_module_handle)
-                               return image->raw_data + addr;
-#endif
                        return (char*)iinfo->cli_sections [i] +
                                (addr - tables->st_virtual_address);
                }
@@ -178,8 +202,15 @@ mono_images_init (void)
 void
 mono_images_cleanup (void)
 {
+       GHashTableIter iter;
+       MonoImage *image;
+
        DeleteCriticalSection (&images_mutex);
 
+       g_hash_table_iter_init (&iter, loaded_images_hash);
+       while (g_hash_table_iter_next (&iter, NULL, (void**)&image))
+               mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly image '%s' still loaded at shutdown.", image->name);
+
        g_hash_table_destroy (loaded_images_hash);
        g_hash_table_destroy (loaded_images_refonly_hash);
 
@@ -995,6 +1026,12 @@ do_mono_image_open (const char *fname, MonoImageOpenStatus *status,
        image->raw_buffer_used = TRUE;
        image->raw_data_len = mono_file_map_size (filed);
        image->raw_data = mono_file_map (image->raw_data_len, MONO_MMAP_READ|MONO_MMAP_PRIVATE, mono_file_map_fd (filed), 0, &image->raw_data_handle);
+#if defined(HAVE_MMAP) && !defined (HOST_WIN32)
+       if (!image->raw_data) {
+               image->fileio_used = TRUE;
+               image->raw_data = mono_file_map_fileio (image->raw_data_len, MONO_MMAP_READ|MONO_MMAP_PRIVATE, mono_file_map_fd (filed), 0, &image->raw_data_handle);
+       }
+#endif
        if (!image->raw_data) {
                mono_file_map_close (filed);
                g_free (image);
@@ -1236,8 +1273,12 @@ mono_image_open_full (const char *fname, MonoImageOpenStatus *status, gboolean r
                        if (status) {
                                if (last_error == ERROR_BAD_EXE_FORMAT || last_error == STATUS_INVALID_IMAGE_FORMAT)
                                        *status = MONO_IMAGE_IMAGE_INVALID;
-                               else
-                                       *status = MONO_IMAGE_ERROR_ERRNO;
+                               else {
+                                       if (last_error == ERROR_FILE_NOT_FOUND || last_error == ERROR_PATH_NOT_FOUND)
+                                               errno = ENOENT;
+                                       else
+                                               errno = 0;
+                               }
                        }
                        return NULL;
                }
@@ -1397,12 +1438,6 @@ free_mr_signatures (gpointer key, gpointer val, gpointer user_data)
 }
 */
 
-static void
-free_remoting_wrappers (gpointer key, gpointer val, gpointer user_data)
-{
-       g_free (val);
-}
-
 static void
 free_array_cache_entry (gpointer key, gpointer val, gpointer user_data)
 {
@@ -1453,7 +1488,6 @@ 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);
 
@@ -1498,7 +1532,7 @@ mono_image_close_except_pools (MonoImage *image)
 
        mono_image_invoke_unload_hook (image);
 
-       free_list = mono_metadata_clean_for_image (image);
+       mono_metadata_clean_for_image (image);
 
        /*
         * The caches inside a MonoImage might refer to metadata which is stored in referenced 
@@ -1506,11 +1540,8 @@ mono_image_close_except_pools (MonoImage *image)
         * MonoImage might outlive its associated MonoAssembly.
         */
        if (image->references && !image->dynamic) {
-               MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLYREF];
-               int i;
-
-               for (i = 0; i < t->rows; i++) {
-                       if (image->references [i]) {
+               for (i = 0; i < image->nreferences; i++) {
+                       if (image->references [i] && image->references [i] != REFERENCE_MISSING) {
                                if (!mono_assembly_close_except_image_pools (image->references [i]))
                                        image->references [i] = NULL;
                        }
@@ -1530,8 +1561,14 @@ mono_image_close_except_pools (MonoImage *image)
 #endif
 
        if (image->raw_buffer_used) {
-               if (image->raw_data != NULL)
-                       mono_file_unmap (image->raw_data, image->raw_data_handle);
+               if (image->raw_data != NULL) {
+#ifndef HOST_WIN32
+                       if (image->fileio_used)
+                               mono_file_unmap_fileio (image->raw_data, image->raw_data_handle);
+                       else
+#endif
+                               mono_file_unmap (image->raw_data, image->raw_data_handle);
+               }
        }
        
        if (image->raw_data_allocated) {
@@ -1585,10 +1622,14 @@ mono_image_close_except_pools (MonoImage *image)
        free_hash (image->delegate_end_invoke_cache);
        free_hash (image->delegate_invoke_cache);
        free_hash (image->delegate_abstract_invoke_cache);
-       if (image->remoting_invoke_cache)
-               g_hash_table_foreach (image->remoting_invoke_cache, free_remoting_wrappers, NULL);
+       free_hash (image->delegate_bound_static_invoke_cache);
+       free_hash (image->delegate_invoke_generic_cache);
+       free_hash (image->delegate_begin_invoke_generic_cache);
+       free_hash (image->delegate_end_invoke_generic_cache);
+       free_hash (image->synchronized_generic_cache);
        free_hash (image->remoting_invoke_cache);
        free_hash (image->runtime_invoke_cache);
+       free_hash (image->runtime_invoke_vtype_cache);
        free_hash (image->runtime_invoke_direct_cache);
        free_hash (image->runtime_invoke_vcall_cache);
        free_hash (image->synchronized_cache);
@@ -1603,11 +1644,16 @@ mono_image_close_except_pools (MonoImage *image)
        free_hash (image->castclass_cache);
        free_hash (image->proxy_isinst_cache);
        free_hash (image->thunk_invoke_cache);
+       free_hash (image->var_cache_slow);
+       free_hash (image->mvar_cache_slow);
+       free_hash (image->wrapper_param_names);
+       free_hash (image->native_wrapper_aot_cache);
+       free_hash (image->pinvoke_scopes);
+       free_hash (image->pinvoke_scope_filenames);
+       free_hash (image->gsharedvt_types);
 
        /* The ownership of signatures is not well defined */
-       //g_hash_table_foreach (image->memberref_signatures, free_mr_signatures, NULL);
        g_hash_table_destroy (image->memberref_signatures);
-       //g_hash_table_foreach (image->helper_signatures, free_mr_signatures, NULL);
        g_hash_table_destroy (image->helper_signatures);
        g_hash_table_destroy (image->method_signatures);
 
@@ -1617,8 +1663,12 @@ mono_image_close_except_pools (MonoImage *image)
        if (image->property_hash)
                mono_property_hash_destroy (image->property_hash);
 
-       g_slist_free (image->reflection_info_unregister_classes);
-       image->reflection_info_unregister_classes = free_list;
+       /*
+       reflection_info_unregister_classes is only required by dynamic images, which will not be properly
+       cleared during shutdown as we don't perform regular appdomain unload for the root one.
+       */
+       g_assert (!image->reflection_info_unregister_classes || mono_runtime_is_shutting_down ());
+       image->reflection_info_unregister_classes = NULL;
 
        if (image->interface_bitset) {
                mono_unload_interface_ids (image->interface_bitset);
@@ -1662,19 +1712,10 @@ 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];
-               int i;
-
-               for (i = 0; i < t->rows; i++) {
-                       if (image->references [i])
+               for (i = 0; i < image->nreferences; i++) {
+                       if (image->references [i] && image->references [i] != REFERENCE_MISSING)
                                mono_assembly_close_finish (image->references [i]);
                }
 
@@ -1689,7 +1730,9 @@ mono_image_close_finish (MonoImage *image)
        if (image->modules)
                g_free (image->modules);
 
+#ifndef DISABLE_PERFCOUNTERS
        mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (image->mempool);
+#endif
 
        if (!image->dynamic) {
                if (debug_assembly_unload)
@@ -2185,7 +2228,9 @@ mono_image_alloc (MonoImage *image, guint size)
 {
        gpointer res;
 
+#ifndef DISABLE_PERFCOUNTERS
        mono_perfcounters->loader_bytes += size;
+#endif
        mono_image_lock (image);
        res = mono_mempool_alloc (image->mempool, size);
        mono_image_unlock (image);
@@ -2198,7 +2243,9 @@ mono_image_alloc0 (MonoImage *image, guint size)
 {
        gpointer res;
 
+#ifndef DISABLE_PERFCOUNTERS
        mono_perfcounters->loader_bytes += size;
+#endif
        mono_image_lock (image);
        res = mono_mempool_alloc0 (image->mempool, size);
        mono_image_unlock (image);
@@ -2211,7 +2258,9 @@ mono_image_strdup (MonoImage *image, const char *s)
 {
        char *res;
 
+#ifndef DISABLE_PERFCOUNTERS
        mono_perfcounters->loader_bytes += strlen (s);
+#endif
        mono_image_lock (image);
        res = mono_mempool_strdup (image->mempool, s);
        mono_image_unlock (image);
@@ -2310,3 +2359,13 @@ mono_image_property_remove (MonoImage *image, gpointer subject)
        mono_property_hash_remove_object (image->property_hash, subject);
        mono_image_unlock (image);
 }
+
+void
+mono_image_append_class_to_reflection_info_set (MonoClass *class)
+{
+       MonoImage *image = class->image;
+       g_assert (image->dynamic);
+       mono_image_lock (image);
+       image->reflection_info_unregister_classes = g_slist_prepend_mempool (image->mempool, image->reflection_info_unregister_classes, class);
+       mono_image_unlock (image);
+}