Merge pull request #2020 from tomjepp/master
[mono.git] / mono / metadata / class.c
index 321fa2eb848e3f87d2b179bdc0ac92c9a295cd71..fdfd5c31505f0ffb427a0655627bf562f558ca27 100644 (file)
@@ -632,7 +632,7 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont
                MonoType *nt;
                int num = mono_type_get_generic_param_num (type);
                MonoGenericInst *inst = context->method_inst;
-               if (!inst || !inst->type_argv)
+               if (!inst)
                        return NULL;
                if (num >= inst->type_argc) {
                        MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
@@ -1009,7 +1009,6 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
        MonoMethodInflated *iresult, *cached;
        MonoMethodSignature *sig;
        MonoGenericContext tmp_context;
-       gboolean is_mb_open = FALSE;
 
        mono_error_init (error);
 
@@ -1041,44 +1040,9 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
                (method->klass->generic_container && context->class_inst)))
                return method;
 
-       /*
-        * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
-        * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
-        * This is opposite to the way non-SRE MethodInfos behave.
-        * 
-        * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
-        * 
-        * void Example<T> () {
-        *    Example<T> ();
-        * }
-        *  
-        * In Example, the method token must be encoded as: "void Example<!!0>()"
-        * 
-        * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
-        * properly. To get that we need to inflate the MethodBuilder with its own arguments.
-        * 
-        * On the other hand, inflating a non-SRE generic method with its own arguments should
-        * return itself. For example:
-        * 
-        * MethodInfo m = ... //m is a generic method definition
-        * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
-        * res == m
-        *
-        * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
-        * what happens with regular methods.
-        * 
-        * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
-        * everything should behave like a regular type or method.
-        * 
-        */
-       is_mb_open = method->is_generic &&
-               image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
-               context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments.  */
-
        iresult = g_new0 (MonoMethodInflated, 1);
        iresult->context = *context;
        iresult->declaring = method;
-       iresult->method.method.is_mb_open = is_mb_open;
 
        if (!context->method_inst && method->is_generic)
                iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
@@ -1094,7 +1058,13 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
        if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
                iresult->context.class_inst = NULL;
 
-       cached = mono_method_inflated_lookup (iresult, FALSE);
+       MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
+
+       // check cache
+       mono_image_set_lock (set);
+       cached = g_hash_table_lookup (set->gmethod_cache, iresult);
+       mono_image_set_unlock (set);
+
        if (cached) {
                g_free (iresult);
                return (MonoMethod*)cached;
@@ -1123,7 +1093,6 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
        result->is_generic = FALSE;
        result->sre_method = FALSE;
        result->signature = NULL;
-       result->is_mb_open = is_mb_open;
 
        if (!context->method_inst) {
                /* Set the generic_container of the result to the generic_container of method */
@@ -1166,7 +1135,17 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
         * is_generic_method_definition().
         */
 
-       return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
+       // check cache
+       mono_image_set_lock (set);
+       cached = g_hash_table_lookup (set->gmethod_cache, iresult);
+       if (!cached) {
+               g_hash_table_insert (set->gmethod_cache, iresult, iresult);
+               iresult->owner = set;
+               cached = iresult;
+       }
+       mono_image_set_unlock (set);
+
+       return (MonoMethod*)cached;
 
 fail:
        g_free (iresult);
@@ -2087,6 +2066,9 @@ mono_class_layout_fields (MonoClass *class)
                        continue;
                if (mono_field_is_deleted (field))
                        continue;
+               // Special static fields do not need a domain-level static slot
+               if (mono_class_field_is_special_static (field))
+                       continue;
 
                if (mono_type_has_exceptions (field->type)) {
                        mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
@@ -7462,18 +7444,21 @@ mono_image_init_name_cache (MonoImage *image)
        const char *name;
        const char *nspace;
        guint32 i, visib, nspace_index;
-       GHashTable *name_cache2, *nspace_table;
+       GHashTable *name_cache2, *nspace_table, *the_name_cache;
 
-       mono_image_lock (image);
-
-       if (image->name_cache) {
-               mono_image_unlock (image);
+       if (image->name_cache)
                return;
-       }
 
-       image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
+       the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
 
        if (image_is_dynamic (image)) {
+               mono_image_lock (image);
+               if (image->name_cache) {
+                       /* Somebody initialized it before us */
+                       g_hash_table_destroy (the_name_cache);
+               } else {
+                       mono_atomic_store_release (&image->name_cache, the_name_cache);
+               }
                mono_image_unlock (image);
                return;
        }
@@ -7497,7 +7482,7 @@ mono_image_init_name_cache (MonoImage *image)
                nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
                if (!nspace_table) {
                        nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
-                       g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
+                       g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
                        g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
                                                                 nspace_table);
                }
@@ -7519,7 +7504,7 @@ mono_image_init_name_cache (MonoImage *image)
                        nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
                        if (!nspace_table) {
                                nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
-                               g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
+                               g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
                                g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
                                                                         nspace_table);
                        }
@@ -7528,6 +7513,14 @@ mono_image_init_name_cache (MonoImage *image)
        }
 
        g_hash_table_destroy (name_cache2);
+
+       mono_image_lock (image);
+       if (image->name_cache) {
+               /* Somebody initialized it before us */
+               g_hash_table_destroy (the_name_cache);
+       } else {
+               mono_atomic_store_release (&image->name_cache, the_name_cache);
+       }
        mono_image_unlock (image);
 }
 
@@ -7540,11 +7533,9 @@ mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
        GHashTable *name_cache;
        guint32 old_index;
 
+       mono_image_init_name_cache (image);
        mono_image_lock (image);
 
-       if (!image->name_cache)
-               mono_image_init_name_cache (image);
-
        name_cache = image->name_cache;
        if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
                nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
@@ -7609,11 +7600,9 @@ mono_class_from_name_case_checked (MonoImage *image, const char* name_space, con
                guint32 token = 0;
                FindUserData user_data;
 
+               mono_image_init_name_cache (image);
                mono_image_lock (image);
 
-               if (!image->name_cache)
-                       mono_image_init_name_cache (image);
-
                user_data.key = name_space;
                user_data.value = NULL;
                g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
@@ -7711,7 +7700,7 @@ search_modules (MonoImage *image, const char *name_space, const char *name)
 }
 
 static MonoClass *
-mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, MonoGHashTable* visited_images)
+mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
 {
        GHashTable *nspace_table;
        MonoImage *loaded_image;
@@ -7724,10 +7713,10 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
        mono_error_init (error);
 
        // Checking visited images avoids stack overflows when cyclic references exist.
-       if (mono_g_hash_table_lookup (visited_images, image))
+       if (g_hash_table_lookup (visited_images, image))
                return NULL;
 
-       mono_g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
+       g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
 
        if ((nested = strchr (name, '/'))) {
                int pos = nested - name;
@@ -7753,11 +7742,9 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
                }
        }
 
+       mono_image_init_name_cache (image);
        mono_image_lock (image);
 
-       if (!image->name_cache)
-               mono_image_init_name_cache (image);
-
        nspace_table = g_hash_table_lookup (image->name_cache, name_space);
 
        if (nspace_table)
@@ -7831,13 +7818,13 @@ MonoClass *
 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
 {
        MonoClass *klass;
-       MonoGHashTable *visited_images;
+       GHashTable *visited_images;
 
-       visited_images = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
+       visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
 
        klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
 
-       mono_g_hash_table_destroy (visited_images);
+       g_hash_table_destroy (visited_images);
 
        return klass;
 }