2009-01-14 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / loader.c
index a2c12a06da867eb0a1210c690fc4dc1497ae4756..8e0b022faa14de8651d7f83e5d5fc8d122da7996 100644 (file)
@@ -507,9 +507,11 @@ find_method_in_class (MonoClass *klass, const char *name, const char *qname, con
                      MonoMethodSignature *sig, MonoClass *from_class)
 {
        int i;
+
        /* Search directly in the metadata to avoid calling setup_methods () */
-       if (klass->type_token && !klass->image->dynamic && !klass->methods && !klass->rank) {
+
+       /* FIXME: !from_class->generic_class condition causes test failures. */
+       if (klass->type_token && !klass->image->dynamic && !klass->methods && !klass->rank && klass == from_class && !from_class->generic_class) {
                for (i = 0; i < klass->method.count; ++i) {
                        guint32 cols [MONO_METHOD_SIZE];
                        MonoMethod *method;
@@ -525,12 +527,8 @@ find_method_in_class (MonoClass *klass, const char *name, const char *qname, con
                                continue;
 
                        method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
-                       if (method && (sig->call_convention != MONO_CALL_VARARG) && mono_metadata_signature_equal (sig, mono_method_signature (method))) {
-                               if (from_class->generic_class && from_class->generic_class->container_class == klass)
-                                       return mono_class_inflate_generic_method_full (method, from_class, mono_class_get_context (from_class));
-                               else
-                                       return method;
-                       }
+                       if (method && (sig->call_convention != MONO_CALL_VARARG) && mono_metadata_signature_equal (sig, mono_method_signature (method)))
+                               return method;
                }
        }
 
@@ -587,10 +585,10 @@ find_method (MonoClass *in_class, MonoClass *ic, const char* name, MonoMethodSig
                if (name [0] == '.' && (!strcmp (name, ".ctor") || !strcmp (name, ".cctor")))
                        break;
 
-               g_assert (from_class->interface_count == in_class->interface_count);
-               for (i = 0; i < in_class->interface_count; i++) {
-                       MonoClass *in_ic = in_class->interfaces [i];
-                       MonoClass *from_ic = from_class->interfaces [i];
+               g_assert (from_class->interface_offsets_count == in_class->interface_offsets_count);
+               for (i = 0; i < in_class->interface_offsets_count; i++) {
+                       MonoClass *in_ic = in_class->interfaces_packed [i];
+                       MonoClass *from_ic = from_class->interfaces_packed [i];
                        char *ic_qname, *ic_fqname, *ic_class_name;
                        
                        ic_class_name = mono_type_get_name_full (&in_ic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
@@ -2049,6 +2047,7 @@ mono_method_get_header (MonoMethod *method)
        MonoImage* img;
        gpointer loc;
        MonoMethodNormal* mn = (MonoMethodNormal*) method;
+       MonoMethodHeader *header;
 
        if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
                return NULL;
@@ -2060,23 +2059,28 @@ mono_method_get_header (MonoMethod *method)
 #endif
                return mn->header;
 
-       mono_loader_lock ();
-
-       if (mn->header) {
-               mono_loader_unlock ();
-               return mn->header;
-       }
-
        if (method->is_inflated) {
                MonoMethodInflated *imethod = (MonoMethodInflated *) method;
                MonoMethodHeader *header;
-               /* the lock is recursive */
+
                header = mono_method_get_header (imethod->declaring);
+
+               mono_loader_lock ();
+
+               if (mn->header) {
+                       mono_loader_unlock ();
+                       return mn->header;
+               }
+
                mn->header = inflate_generic_header (header, mono_method_get_context (method));
                mono_loader_unlock ();
                return mn->header;
        }
 
+       /* 
+        * Do most of the work outside the loader lock, to avoid assembly loader hook
+        * deadlocks.
+        */
        g_assert (mono_metadata_token_table (method->token) == MONO_TABLE_METHOD);
        idx = mono_metadata_token_index (method->token);
        img = method->klass->image;
@@ -2085,7 +2089,19 @@ mono_method_get_header (MonoMethod *method)
 
        g_assert (loc);
 
-       mn->header = mono_metadata_parse_mh_full (img, mono_method_get_generic_container (method), loc);
+       header = mono_metadata_parse_mh_full (img, mono_method_get_generic_container (method), loc);
+
+       mono_loader_lock ();
+
+       if (mn->header) {
+               /* header is allocated from the image mempool, no need to free it */
+               mono_loader_unlock ();
+               return mn->header;
+       }
+
+       mono_memory_barrier ();
+
+       mn->header = header;
 
        mono_loader_unlock ();
        return mn->header;