Make the thread dump code safe by doing only async safe operations when a thread...
[mono.git] / mono / metadata / class.c
index 5ed261ffbbe468a2a825601134e8c516a710515c..d733afeed2a66a9fa4c5ec3f56a9714726e1b626 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);
@@ -7467,17 +7446,16 @@ mono_image_init_name_cache (MonoImage *image)
        if (image->name_cache)
                return;
 
-       mono_image_lock (image);
-
-       if (image->name_cache) {
-               mono_image_unlock (image);
-               return;
-       }
-
        the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
 
        if (image_is_dynamic (image)) {
-               mono_atomic_store_release (&image->name_cache, the_name_cache);
+               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;
        }
@@ -7532,7 +7510,14 @@ mono_image_init_name_cache (MonoImage *image)
        }
 
        g_hash_table_destroy (name_cache2);
-       mono_atomic_store_release (&image->name_cache, the_name_cache);
+
+       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);
 }
 
@@ -7712,7 +7697,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;
@@ -7725,10 +7710,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;
@@ -7830,13 +7815,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;
 }