From 5b16e28208b4b0d19c186652f4c4de8d5cd9048c Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Mon, 14 Dec 2009 23:52:55 +0000 Subject: [PATCH] 2009-12-15 Mark Probst * class.c (mono_generic_class_get_class): Allocate the generic class via malloc again, so that it can be freed when any one of the images of its constituent types is closed. * metadata.c: When closing an image, don't free generic insts and generic classes right away, but put them into a list for later freeing. * image.c, metadata-internals.h: Store the free list and in the second pass of closing an image, free it. svn path=/trunk/mono/; revision=148438 --- mono/metadata/ChangeLog | 13 ++++++++++ mono/metadata/class.c | 6 ++--- mono/metadata/image.c | 10 +++++++- mono/metadata/metadata-internals.h | 7 +++++- mono/metadata/metadata.c | 50 +++++++++++++++++++++++++++++--------- 5 files changed, 69 insertions(+), 17 deletions(-) diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index 27c48eed105..f5278531297 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,16 @@ +2009-12-15 Mark Probst + + * class.c (mono_generic_class_get_class): Allocate the generic + class via malloc again, so that it can be freed when any one of + the images of its constituent types is closed. + + * metadata.c: When closing an image, don't free generic insts and + generic classes right away, but put them into a list for later + freeing. + + * image.c, metadata-internals.h: Store the free list and in the + second pass of closing an image, free it. + 2009-12-14 Rodrigo Kumpera * reflection.c (mono_generic_class_get_object): Assert if this is ever called. diff --git a/mono/metadata/class.c b/mono/metadata/class.c index fe21a51a34f..a134a8a316c 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -4751,11 +4751,11 @@ mono_generic_class_get_class (MonoGenericClass *gclass) return gclass->cached_class; } - gklass = gclass->container_class; - - gclass->cached_class = mono_image_alloc0 (gklass->image, sizeof (MonoClass)); + gclass->cached_class = g_malloc0 (sizeof (MonoClass)); klass = gclass->cached_class; + gklass = gclass->container_class; + if (gklass->nested_in) { /* * FIXME: the nested type context should include everything the diff --git a/mono/metadata/image.c b/mono/metadata/image.c index 53327041559..82649e875d0 100644 --- a/mono/metadata/image.c +++ b/mono/metadata/image.c @@ -1417,6 +1417,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 +1460,7 @@ 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); + free_list = mono_metadata_clean_for_image (image); /* * The caches inside a MonoImage might refer to metadata which is stored in referenced @@ -1582,6 +1583,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 +1627,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]; diff --git a/mono/metadata/metadata-internals.h b/mono/metadata/metadata-internals.h index 4d7071fd338..19d2c946efe 100644 --- a/mono/metadata/metadata-internals.h +++ b/mono/metadata/metadata-internals.h @@ -254,6 +254,8 @@ struct _MonoImage { /* interfaces IDs from this image */ MonoBitSet *interface_bitset; + /* when the image is being closed, this is abused as a list of + malloc'ed regions to be freed. */ GSList *reflection_info_unregister_classes; /* @@ -423,10 +425,13 @@ mono_image_close_finish (MonoImage *image) MONO_INTERNAL; MonoType* mono_metadata_get_shared_type (MonoType *type) MONO_INTERNAL; -void +GSList* mono_metadata_clean_for_image (MonoImage *image) MONO_INTERNAL; void +mono_metadata_clean_generic_classes_for_image (MonoImage *image) MONO_INTERNAL; + +void mono_metadata_cleanup (void); const char * mono_meta_table_name (int table) MONO_INTERNAL; diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index e8fd8155ca6..2576de984dc 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -39,7 +39,9 @@ static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolea static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only); static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only); +static GSList* free_generic_inst_dependents (MonoGenericInst *ginst); static void free_generic_inst (MonoGenericInst *ginst); +static GSList* free_generic_class_dependents (MonoGenericClass *ginst); static void free_generic_class (MonoGenericClass *ginst); static void free_inflated_method (MonoMethodInflated *method); static void mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image); @@ -2237,17 +2239,15 @@ inflated_signature_in_image (gpointer key, gpointer value, gpointer data) (sig->context.method_inst && ginst_in_image (sig->context.method_inst, image)); } -void +GSList* mono_metadata_clean_for_image (MonoImage *image) { CleanForImageUserData ginst_data, gclass_data; - GSList *l; - + GSList *l, *free_list = NULL; /* The data structures could reference each other so we delete them in two phases */ ginst_data.image = gclass_data.image = image; ginst_data.list = gclass_data.list = NULL; - - mono_loader_lock (); + mono_loader_lock (); /* Collect the items to delete and remove them from the hash table */ g_hash_table_foreach_steal (generic_inst_cache, steal_ginst_in_image, &ginst_data); g_hash_table_foreach_steal (generic_class_cache, steal_gclass_in_image, &gclass_data); @@ -2257,13 +2257,15 @@ mono_metadata_clean_for_image (MonoImage *image) g_hash_table_foreach_remove (generic_signature_cache, inflated_signature_in_image, image); /* Delete the removed items */ for (l = ginst_data.list; l; l = l->next) - free_generic_inst (l->data); + free_list = g_slist_concat (free_generic_inst_dependents (l->data), free_list); for (l = gclass_data.list; l; l = l->next) - free_generic_class (l->data); + free_list = g_slist_concat (free_generic_class_dependents (l->data), free_list); g_slist_free (ginst_data.list); g_slist_free (gclass_data.list); mono_class_unregister_image_generic_subclasses (image); mono_loader_unlock (); + + return free_list; } static void @@ -2294,19 +2296,34 @@ free_inflated_method (MonoMethodInflated *imethod) } static void -free_generic_inst (MonoGenericInst *ginst) +free_list_with_data (GSList *l) +{ + while (l) { + g_free (l->data); + l = g_slist_delete_link (l, l); + } +} + +static GSList* +free_generic_inst_dependents (MonoGenericInst *ginst) { int i; for (i = 0; i < ginst->type_argc; ++i) mono_metadata_free_type (ginst->type_argv [i]); - g_free (ginst); + return g_slist_prepend (NULL, ginst); } - static void -free_generic_class (MonoGenericClass *gclass) +free_generic_inst (MonoGenericInst *ginst) +{ + free_list_with_data (free_generic_inst_dependents (ginst)); +} + +static GSList* +free_generic_class_dependents (MonoGenericClass *gclass) { + GSList *l = NULL; int i; /* FIXME: The dynamic case */ @@ -2319,6 +2336,7 @@ free_generic_class (MonoGenericClass *gclass) g_free (class->ext->properties); /* Allocated in mono_generic_class_get_class () */ g_free (class->interfaces); + l = g_slist_prepend (l, class); } else if (gclass->is_dynamic) { MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *)gclass; @@ -2346,8 +2364,16 @@ free_generic_class (MonoGenericClass *gclass) g_free (dgclass->events); g_free (dgclass->field_objects); g_free (dgclass->field_generic_types); + if (!mono_generic_class_is_generic_type_definition (gclass)) + l = g_slist_prepend (l, gclass->cached_class); } - g_free (gclass); + return g_slist_prepend (l, gclass); +} + +static void +free_generic_class (MonoGenericClass *gclass) +{ + free_list_with_data (free_generic_class_dependents (gclass)); } static void -- 2.11.4.GIT