Merge pull request #2237 from xmcclure/container-owner
[mono.git] / mono / metadata / metadata.c
index 9ad1de0f37f18f9d10ec5e5baa5157b9f8512497..7aa5300a753aaeebd2063a4603a4b57195efea61 100644 (file)
@@ -1493,10 +1493,14 @@ mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b
 {
        int i;
 
-#ifndef MONO_SMALL_CONFIG
-       if (a->id && b->id) {
+       // An optimization: if the ids of two insts are the same, we know they are the same inst and don't check contents.
+       // Furthermore, because we perform early de-duping, if the ids differ, we know the contents differ.
+#ifndef MONO_SMALL_CONFIG // Optimization does not work in MONO_SMALL_CONFIG: There are no IDs
+       if (a->id && b->id) { // "id 0" means "object has no id"-- de-duping hasn't been performed yet, must check contents.
                if (a->id == b->id)
                        return TRUE;
+               // In signature-comparison mode id equality implies object equality, but this is not true for inequality.
+               // Two separate objects could have signature-equavalent contents.
                if (!signature_only)
                        return FALSE;
        }
@@ -1558,7 +1562,7 @@ mono_metadata_init (void)
        for (i = 0; i < NBUILTIN_TYPES (); ++i)
                g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
 
-       mono_mutex_init_recursive (&image_sets_mutex);
+       mono_os_mutex_init_recursive (&image_sets_mutex);
 }
 
 /**
@@ -1574,7 +1578,7 @@ mono_metadata_cleanup (void)
        type_cache = NULL;
        g_ptr_array_free (image_sets, TRUE);
        image_sets = NULL;
-       mono_mutex_destroy (&image_sets_mutex);
+       mono_os_mutex_destroy (&image_sets_mutex);
 }
 
 /**
@@ -1612,7 +1616,7 @@ mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container
        gboolean byref = FALSE;
        gboolean pinned = FALSE;
        const char *tmp_ptr;
-       int count = 0;
+       int count = 0; // Number of mod arguments
        gboolean found;
 
        /*
@@ -1646,7 +1650,7 @@ mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container
                }
        }
 
-       if (count) {
+       if (count) { // There are mods, so the MonoType will be of nonstandard size.
                int size;
 
                size = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
@@ -1654,12 +1658,12 @@ mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container
                type->num_mods = count;
                if (count > 64)
                        g_warning ("got more than 64 modifiers in type");
-       } else {
+       } else {     // The type is of standard size, so we can allocate it on the stack.
                type = &stype;
                memset (type, 0, MONO_SIZEOF_TYPE);
        }
 
-       /* Parse pinned, byref and custom modifiers */
+       /* Iterate again, but now parse pinned, byref and custom modifiers */
        found = TRUE;
        count = 0;
        while (found) {
@@ -1695,6 +1699,7 @@ mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container
        if (rptr)
                *rptr = ptr;
 
+       // Possibly we can return an already-allocated type instead of the one we decoded
        if (!type->num_mods && !transient) {
                /* no need to free type here, because it is on the stack */
                if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
@@ -1730,7 +1735,7 @@ mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container
        
        /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
        
-       if (type == &stype) {
+       if (type == &stype) { // Type was allocated on the stack, so we need to copy it to safety
                type = transient ? g_malloc (MONO_SIZEOF_TYPE) : mono_image_alloc (m, MONO_SIZEOF_TYPE);
                memcpy (type, &stype, MONO_SIZEOF_TYPE);
        }
@@ -2301,13 +2306,13 @@ retry:
 static inline void
 image_sets_lock (void)
 {
-       mono_mutex_lock (&image_sets_mutex);
+       mono_os_mutex_lock (&image_sets_mutex);
 }
 
 static inline void
 image_sets_unlock (void)
 {
-       mono_mutex_unlock (&image_sets_mutex);
+       mono_os_mutex_unlock (&image_sets_mutex);
 }
 
 /*
@@ -2322,11 +2327,12 @@ get_image_set (MonoImage **images, int nimages)
        MonoImageSet *set;
        GSList *l;
 
-       /* Common case */
+       /* Common case: Image set contains corlib only. If we've seen that case before, we cached the set. */
        if (nimages == 1 && images [0] == mono_defaults.corlib && mscorlib_image_set)
                return mscorlib_image_set;
 
        /* Happens with empty generic instances */
+       // FIXME: Is corlib the correct thing to return here? If so, why? This may be an artifact of generic instances previously defaulting to allocating from corlib.
        if (nimages == 0)
                return mscorlib_image_set;
 
@@ -2335,43 +2341,51 @@ get_image_set (MonoImage **images, int nimages)
        if (!image_sets)
                image_sets = g_ptr_array_new ();
 
+       // Before we go on, we should check to see whether a MonoImageSet with these images already exists.
+       // We can search the referred-by imagesets of any one of our images to do this. Arbitrarily pick one here:
        if (images [0] == mono_defaults.corlib && nimages > 1)
-               l = images [1]->image_sets;
+               l = images [1]->image_sets; // Prefer not to search the imagesets of corlib-- that will be a long list.
        else
                l = images [0]->image_sets;
 
        set = NULL;
-       for (; l; l = l->next) {
+       while (l) // Iterate over selected list, looking for an imageset with members equal to our target one
+       {
                set = l->data;
 
-               if (set->nimages == nimages) {
+               if (set->nimages == nimages) { // Member count differs, this can't be it
+                       // Compare all members to all members-- order might be different
                        for (j = 0; j < nimages; ++j) {
                                for (k = 0; k < nimages; ++k)
                                        if (set->images [k] == images [j])
-                                               break;
+                                               break; // Break on match
+
+                               // If we iterated all the way through set->images, images[j] was *not* found.
                                if (k == nimages)
-                                       /* Not found */
-                                       break;
+                                       break; // Break on "image not found"
                        }
+
+                       // If we iterated all the way through images without breaking, all items in images were found in set->images
                        if (j == nimages)
-                               /* Found */
-                               break;
+                               break; // Break on "found a set with equal members"
                }
+
+               l = l->next;
        }
 
+       // If we iterated all the way through l without breaking, the imageset does not already exist and we shuold create it
        if (!l) {
-               /* Not found */
                set = g_new0 (MonoImageSet, 1);
                set->nimages = nimages;
                set->images = g_new0 (MonoImage*, nimages);
-               mono_mutex_init_recursive (&set->lock);
+               mono_os_mutex_init_recursive (&set->lock);
                for (i = 0; i < nimages; ++i)
                        set->images [i] = images [i];
                set->gclass_cache = g_hash_table_new_full (mono_generic_class_hash, mono_generic_class_equal, NULL, (GDestroyNotify)free_generic_class);
                set->ginst_cache = g_hash_table_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst);
                set->gmethod_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method);
                set->gsignature_cache = g_hash_table_new_full (inflated_signature_hash, inflated_signature_equal, NULL, (GDestroyNotify)free_inflated_signature);
-       
+
                for (i = 0; i < nimages; ++i)
                        set->images [i]->image_sets = g_slist_prepend (set->images [i]->image_sets, set);
 
@@ -2412,20 +2426,20 @@ delete_image_set (MonoImageSet *set)
        if (set->mempool)
                mono_mempool_destroy (set->mempool);
        g_free (set->images);
-       mono_mutex_destroy (&set->lock);
+       mono_os_mutex_destroy (&set->lock);
        g_free (set);
 }
 
 void
 mono_image_set_lock (MonoImageSet *set)
 {
-       mono_mutex_lock (&set->lock);
+       mono_os_mutex_lock (&set->lock);
 }
 
 void
 mono_image_set_unlock (MonoImageSet *set)
 {
-       mono_mutex_unlock (&set->lock);
+       mono_os_mutex_unlock (&set->lock);
 }
 
 gpointer
@@ -2966,12 +2980,11 @@ mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst
        MonoImageSet *set;
        CollectData data;
 
+       memset (&helper, 0, sizeof(helper)); // act like g_new0
        helper.container_class = container_class;
        helper.context.class_inst = inst;
-       helper.context.method_inst = NULL;
        helper.is_dynamic = is_dynamic; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
        helper.is_tb_open = is_tb_open;
-       helper.cached_class = NULL;
 
        collect_data_init (&data);
 
@@ -5001,6 +5014,7 @@ mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gbo
  * mono_metadata_type_equal:
  * @t1: a type
  * @t2: another type
+ * @signature_only: If true, treat ginsts as equal which are instantiated separately but have equal positional value
  *
  * Determine if @t1 and @t2 represent the same type.
  * Returns: #TRUE if @t1 and @t2 are equal.