Mon Oct 15 10:20:56 CEST 2007 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / class.c
index 3d134014f6eabab3a306181f7064d710ccce59bb..a2ca00d32f35bf58cc0a07a78c3bb1e1c7804803 100644 (file)
@@ -20,6 +20,7 @@
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/profiler-private.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/tokentype.h>
 #include <mono/metadata/class-internals.h>
@@ -533,6 +534,9 @@ inflate_generic_type (MonoType *type, MonoGenericContext *context)
 
                /* We can't use context->class_inst directly, since it can have more elements */
                inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context);
+               if (inst == container->context.class_inst)
+                       return NULL;
+
                gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic);
 
                nt = mono_metadata_type_dup (NULL, type);
@@ -1287,6 +1291,8 @@ mono_class_setup_methods (MonoClass *class)
                for (i = 0; i < class->method.count; ++i) {
                        int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
                        methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
+                       if (class->valuetype && methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED && !(methods [i]->flags & MONO_METHOD_ATTR_STATIC))
+                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
                }
        }
 
@@ -1753,6 +1759,186 @@ print_implemented_interfaces (MonoClass *klass) {
        }
 }
 
+/* this won't be needed once bug #325495 is completely fixed
+ * though we'll need something similar to know which interfaces to allow
+ * in arrays when they'll be lazyly created
+ */
+static MonoClass**
+get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
+{
+       MonoClass *eclass = class->element_class;
+       static MonoClass* generic_icollection_class = NULL;
+       static MonoClass* generic_ienumerable_class = NULL;
+       static MonoClass* generic_ienumerator_class = NULL;
+       MonoClass *fclass = NULL;
+       MonoClass **interfaces = NULL;
+       int i, interface_count, real_count;
+       int all_interfaces;
+       gboolean internal_enumerator;
+       gboolean eclass_is_valuetype;
+
+       if (!mono_defaults.generic_ilist_class) {
+               *num = 0;
+               return NULL;
+       }
+       internal_enumerator = FALSE;
+       eclass_is_valuetype = FALSE;
+       if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
+               if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0)  {
+                       /*
+                        * For a Enumerator<T[]> we need to get the list of interfaces for T.
+                        */
+                       eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
+                       eclass = eclass->element_class;
+                       internal_enumerator = TRUE;
+                       *is_enumerator = TRUE;
+               } else {
+                       *num = 0;
+                       return NULL;
+               }
+       }
+
+       /* 
+        * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
+        * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
+        */
+       all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
+
+       if (!generic_icollection_class) {
+               generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
+                       "System.Collections.Generic", "ICollection`1");
+               generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
+                       "System.Collections.Generic", "IEnumerable`1");
+               generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
+                       "System.Collections.Generic", "IEnumerator`1");
+       }
+
+       /*
+        * Arrays in 2.0 need to implement a number of generic interfaces
+        * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
+        * on the element class). We collect the types needed to build the
+        * instantiations in interfaces at intervals of 3, because 3 are
+        * the generic interfaces needed to implement.
+        */
+       if (eclass->valuetype) {
+               if (eclass == mono_defaults.int16_class)
+                       fclass = mono_defaults.uint16_class;
+               else if (eclass == mono_defaults.uint16_class)
+                       fclass = mono_defaults.int16_class;
+               else if (eclass == mono_defaults.int32_class)
+                       fclass = mono_defaults.uint32_class;
+               else if (eclass == mono_defaults.uint32_class)
+                       fclass = mono_defaults.int32_class;
+               else if (eclass == mono_defaults.int64_class)
+                       fclass = mono_defaults.uint64_class;
+               else if (eclass == mono_defaults.uint64_class)
+                       fclass = mono_defaults.int64_class;
+               else if (eclass == mono_defaults.byte_class)
+                       fclass = mono_defaults.sbyte_class;
+               else if (eclass == mono_defaults.sbyte_class)
+                       fclass = mono_defaults.byte_class;
+               else {
+                       /* No additional interfaces for other value types */
+                       *num = 0;
+                       return NULL;
+               }
+
+               /* IList, ICollection, IEnumerable */
+               real_count = interface_count = 3;
+               interfaces = g_malloc0 (sizeof (MonoClass*) * interface_count);
+               interfaces [0] = fclass;
+               eclass_is_valuetype = TRUE;
+       } else {
+               int j;
+               int idepth = eclass->idepth;
+               if (!internal_enumerator)
+                       idepth--;
+               interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
+               /* we add object for interfaces and the supertypes for the other
+                * types. The last of the supertypes is the element class itself which we
+                * already created the explicit interfaces for (so we include it for IEnumerator
+                * and exclude it for arrays).
+                */
+               if (MONO_CLASS_IS_INTERFACE (eclass))
+                       interface_count++;
+               else
+                       interface_count += idepth;
+               /* IList, ICollection, IEnumerable */
+               interface_count *= 3;
+               real_count = interface_count;
+               if (internal_enumerator)
+                       real_count += idepth;
+               interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
+               if (MONO_CLASS_IS_INTERFACE (eclass)) {
+                       interfaces [0] = mono_defaults.object_class;
+                       j = 3;
+               } else {
+                       j = 0;
+                       for (i = 0; i < idepth; i++) {
+                               mono_class_init (eclass->supertypes [i]);
+                               interfaces [j] = eclass->supertypes [i];
+                               j += 3;
+                       }
+               }
+               if (all_interfaces) {
+                       for (i = 0; i < eclass->interface_offsets_count; i++) {
+                               interfaces [j] = eclass->interfaces_packed [i];
+                               j += 3;
+                       }
+               } else {
+                       for (i = 0; i < eclass->interface_count; i++) {
+                               interfaces [j] = eclass->interfaces [i];
+                               j += 3;
+                       }
+               }
+       }
+
+       /* instantiate the generic interfaces */
+       for (i = 0; i < interface_count; i += 3) {
+               MonoType *args [1];
+               MonoClass *iface = interfaces [i];
+
+               args [0] = &iface->byval_arg;
+               interfaces [i] = mono_class_bind_generic_parameters (
+                       mono_defaults.generic_ilist_class, 1, args, FALSE);
+               //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));
+               args [0] = &iface->byval_arg;
+               interfaces [i + 1] = mono_class_bind_generic_parameters (
+                       generic_icollection_class, 1, args, FALSE);
+               args [0] = &iface->byval_arg;
+               interfaces [i + 2] = mono_class_bind_generic_parameters (
+                       generic_ienumerable_class, 1, args, FALSE);
+               //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i + 1]->byval_arg, 0));
+               //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i + 2]->byval_arg, 0));
+       }
+       if (internal_enumerator) {
+               int j;
+               /* instantiate IEnumerator<iface> */
+               for (i = 0; i < interface_count; i++) {
+                       MonoType *args [1];
+                       MonoClass *iface = interfaces [i];
+
+                       args [0] = &iface->byval_arg;
+                       interfaces [i] = mono_class_bind_generic_parameters (
+                               generic_ienumerator_class, 1, args, FALSE);
+                       /*g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));*/
+               }
+               if (!eclass_is_valuetype) {
+                       j = interface_count;
+                       for (i = 0; i < eclass->idepth; i++) {
+                               MonoType *args [1];
+                               args [0] = &eclass->supertypes [i]->byval_arg;
+                               interfaces [j] = mono_class_bind_generic_parameters (
+                                       generic_ienumerator_class, 1, args, FALSE);
+                               /*g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));*/
+                               j ++;
+                       }
+               }
+       }
+       *num = real_count;
+       return interfaces;
+}
+
 /*
  * LOCKING: this is supposed to be called with the loader lock held.
  */
@@ -1765,6 +1951,16 @@ setup_interface_offsets (MonoClass *class, int cur_slot)
        int *interface_offsets_full;
        GPtrArray *ifaces;
        int interface_offsets_count;
+       MonoClass **array_interfaces;
+       int num_array_interfaces;
+       int is_enumerator = FALSE;
+
+       /* 
+        * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
+        * implicit innterfaces have the property that they are assigned the same slot in the vtables
+        * for compatible interfaces
+        */
+       array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
 
        /* compute maximum number of slots and maximum interface id */
        max_iid = 0;
@@ -1788,6 +1984,12 @@ setup_interface_offsets (MonoClass *class, int cur_slot)
                        g_ptr_array_free (ifaces, TRUE);
                }
        }
+       for (i = 0; i < num_array_interfaces; ++i) {
+               ic = array_interfaces [i];
+               mono_class_init (ic);
+               if (max_iid < ic->interface_id)
+                       max_iid = ic->interface_id;
+       }
 
        if (MONO_CLASS_IS_INTERFACE (class)) {
                if (max_iid < class->interface_id)
@@ -1838,6 +2040,45 @@ setup_interface_offsets (MonoClass *class, int cur_slot)
                interface_offsets_full [class->interface_id] = cur_slot;
        }
 
+       if (num_array_interfaces) {
+               if (is_enumerator) {
+                       int ienumerator_offset;
+                       g_assert (strcmp (class->interfaces [0]->name, "IEnumerator`1") == 0);
+                       ienumerator_offset = interface_offsets_full [class->interfaces [0]->interface_id];
+                       for (i = 0; i < num_array_interfaces; ++i) {
+                               ic = array_interfaces [i];
+                               interfaces_full [ic->interface_id] = ic;
+                               if (strcmp (ic->name, "IEnumerator`1") == 0)
+                                       interface_offsets_full [ic->interface_id] = ienumerator_offset;
+                               else
+                                       g_assert_not_reached ();
+                               /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, interface_offsets_full [ic->interface_id], class->interfaces [0]->name);*/
+                       }
+               } else {
+                       int ilist_offset, icollection_offset, ienumerable_offset;
+                       g_assert (strcmp (class->interfaces [0]->name, "IList`1") == 0);
+                       g_assert (strcmp (class->interfaces [0]->interfaces [0]->name, "ICollection`1") == 0);
+                       g_assert (strcmp (class->interfaces [0]->interfaces [1]->name, "IEnumerable`1") == 0);
+                       ilist_offset = interface_offsets_full [class->interfaces [0]->interface_id];
+                       icollection_offset = interface_offsets_full [class->interfaces [0]->interfaces [0]->interface_id];
+                       ienumerable_offset = interface_offsets_full [class->interfaces [0]->interfaces [1]->interface_id];
+                       g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
+                       for (i = 0; i < num_array_interfaces; ++i) {
+                               ic = array_interfaces [i];
+                               interfaces_full [ic->interface_id] = ic;
+                               if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
+                                       interface_offsets_full [ic->interface_id] = ilist_offset;
+                               else if (strcmp (ic->name, "ICollection`1") == 0)
+                                       interface_offsets_full [ic->interface_id] = icollection_offset;
+                               else if (strcmp (ic->name, "IEnumerable`1") == 0)
+                                       interface_offsets_full [ic->interface_id] = ienumerable_offset;
+                               else
+                                       g_assert_not_reached ();
+                               /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, interface_offsets_full [ic->interface_id], class->interfaces [0]->name);*/
+                       }
+               }
+       }
+
        for (interface_offsets_count = 0, i = 0; i <= max_iid; i++) {
                if (interface_offsets_full [i] != -1) {
                        interface_offsets_count ++;
@@ -1852,12 +2093,15 @@ setup_interface_offsets (MonoClass *class, int cur_slot)
                        class->interface_bitmap [i >> 3] |= (1 << (i & 7));
                        class->interfaces_packed [interface_offsets_count] = interfaces_full [i];
                        class->interface_offsets_packed [interface_offsets_count] = interface_offsets_full [i];
+                       /*if (num_array_interfaces)
+                               g_print ("type %s has %s offset at %d\n", mono_type_get_name_full (&class->byval_arg, 0), mono_type_get_name_full (&interfaces_full [i]->byval_arg, 0), interface_offsets_full [i]);*/
                        interface_offsets_count ++;
                }
        }
        
        g_free (interfaces_full);
        g_free (interface_offsets_full);
+       g_free (array_interfaces);
        
        //printf ("JUST DONE: ");
        //print_implemented_interfaces (class);
@@ -2432,21 +2676,36 @@ g_list_prepend_mempool (GList* l, MonoMemPool* mp, gpointer datum)
        return n;
 }
 
-static void
-setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, int pos)
-{
-       MonoGenericContext tmp_context;
-       int i;
+typedef struct {
+       MonoMethod *array_method;
+       char *name;
+} GenericArrayMethodInfo;
 
-       tmp_context.class_inst = NULL;
-       tmp_context.method_inst = iface->generic_class->context.class_inst;
+static int generic_array_method_num = 0;
+static GenericArrayMethodInfo *generic_array_method_info = NULL;
 
+static int
+generic_array_methods (MonoClass *class)
+{
+       int i, count_generic = 0;
+       GList *list = NULL, *tmp;
+       if (generic_array_method_num)
+               return generic_array_method_num;
        for (i = 0; i < class->parent->method.count; i++) {
                MonoMethod *m = class->parent->methods [i];
-               MonoMethod *inflated;
+               if (!strncmp (m->name, "InternalArray__", 15)) {
+                       count_generic++;
+                       list = g_list_prepend (list, m);
+               }
+       }
+       list = g_list_reverse (list);
+       generic_array_method_info = g_malloc (sizeof (GenericArrayMethodInfo) * count_generic);
+       i = 0;
+       for (tmp = list; tmp; tmp = tmp->next) {
                const char *mname, *iname;
                gchar *name;
-
+               MonoMethod *m = tmp->data;
+               generic_array_method_info [i].array_method = m;
                if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
                        iname = "System.Collections.Generic.ICollection`1.";
                        mname = m->name + 27;
@@ -2457,15 +2716,37 @@ setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, int pos)
                        iname = "System.Collections.Generic.IList`1.";
                        mname = m->name + 15;
                } else {
-                       continue;
+                       g_assert_not_reached ();
                }
 
-               name = mono_mempool_alloc (class->image->mempool, strlen (iname) + strlen (mname) + 1);
+               name = mono_mempool_alloc (mono_defaults.corlib->mempool, strlen (iname) + strlen (mname) + 1);
                strcpy (name, iname);
                strcpy (name + strlen (iname), mname);
+               generic_array_method_info [i].name = name;
+               i++;
+       }
+       /*g_print ("array generic methods: %d\n", count_generic);*/
+
+       generic_array_method_num = count_generic;
+       return generic_array_method_num;
+}
+
+static void
+setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, int pos)
+{
+       MonoGenericContext tmp_context;
+       int i;
+
+       tmp_context.class_inst = NULL;
+       tmp_context.method_inst = iface->generic_class->context.class_inst;
+       //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
+
+       for (i = 0; i < generic_array_method_num; i++) {
+               MonoMethod *m = generic_array_method_info [i].array_method;
+               MonoMethod *inflated;
 
                inflated = mono_class_inflate_generic_method (m, &tmp_context);
-               class->methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, name, inflated);
+               class->methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
        }
 }
 
@@ -2694,11 +2975,7 @@ mono_class_init (MonoClass *class)
                class->method.count = 3 + (class->rank > 1? 2: 1);
 
                if (class->interface_count) {
-                       for (i = 0; i < class->parent->method.count; i++) {
-                               MonoMethod *m = class->parent->methods [i];
-                               if (!strncmp (m->name, "InternalArray__", 15))
-                                       count_generic++;
-                       }
+                       count_generic = generic_array_methods (class);
                        first_generic = class->method.count;
                        class->method.count += class->interface_count * count_generic;
                }
@@ -3128,6 +3405,8 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        class->name = name;
        class->name_space = nspace;
 
+       mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
+
        class->image = image;
        class->type_token = type_token;
        class->flags = cols [MONO_TYPEDEF_FLAGS];
@@ -3149,6 +3428,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                if (parent == NULL){
                        mono_internal_hash_table_remove (&image->class_cache, GUINT_TO_POINTER (type_token));
                        mono_loader_unlock ();
+                       mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
                        return NULL;
                }
        }
@@ -3166,6 +3446,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                if (!mono_metadata_interfaces_from_typedef_full (
                            image, type_token, &interfaces, &icount, context)){
                        mono_loader_unlock ();
+                       mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
                        return NULL;
                }
 
@@ -3238,6 +3519,8 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 
        mono_loader_unlock ();
 
+       mono_profiler_class_loaded (class, MONO_PROFILE_OK);
+
        return class;
 }
 
@@ -3271,7 +3554,6 @@ mono_generic_class_get_class (MonoGenericClass *gclass)
        mono_loader_lock ();
        if (gclass->cached_class) {
                mono_loader_unlock ();
-               g_assert (!gclass->cached_class->generic_container);
                return gclass->cached_class;
        }
 
@@ -3389,6 +3671,15 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb
 
        klass = param->pklass = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
 
+       if (param->name)
+               klass->name = param->name;
+       else {
+               klass->name = mono_mempool_alloc0 (image->mempool, 16);
+               sprintf ((char*)klass->name, is_mvar ? "!!%d" : "!%d", param->num);
+       }
+       klass->name_space = "";
+       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+       
        for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
                ;
 
@@ -3408,15 +3699,6 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb
                        klass->interfaces [i - pos] = param->constraints [i];
        }
 
-       if (param->name)
-               klass->name = param->name;
-       else {
-               klass->name = mono_mempool_alloc0 (image->mempool, 16);
-               sprintf ((char*)klass->name, is_mvar ? "!!%d" : "!%d", param->num);
-       }
-
-       klass->name_space = "";
-
        if (!image)
                image = mono_defaults.corlib;
 
@@ -3434,7 +3716,9 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb
        mono_class_setup_supertypes (klass);
 
        mono_loader_unlock ();
-       
+
+       mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+
        return klass;
 }
 
@@ -3465,6 +3749,9 @@ mono_ptr_class_get (MonoType *type)
        name = g_strdup_printf ("%s*", el_class->name);
        result->name = mono_mempool_strdup (image->mempool, name);
        g_free (name);
+
+       mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
+
        result->image = el_class->image;
        result->inited = TRUE;
        result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
@@ -3484,6 +3771,8 @@ mono_ptr_class_get (MonoType *type)
 
        mono_loader_unlock ();
 
+       mono_profiler_class_loaded (result, MONO_PROFILE_OK);
+
        return result;
 }
 
@@ -3509,6 +3798,9 @@ mono_fnptr_class_get (MonoMethodSignature *sig)
        result->parent = NULL; /* no parent for PTR types */
        result->name_space = "System";
        result->name = "MonoFNPtrFakeClass";
+
+       mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
+
        result->image = mono_defaults.corlib; /* need to fix... */
        result->inited = TRUE;
        result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
@@ -3529,6 +3821,8 @@ mono_fnptr_class_get (MonoMethodSignature *sig)
 
        mono_loader_unlock ();
 
+       mono_profiler_class_loaded (result, MONO_PROFILE_OK);
+
        return result;
 }
 
@@ -3699,6 +3993,9 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
        name [nsize + rank + 1] = 0;
        class->name = mono_mempool_strdup (image->mempool, name);
        g_free (name);
+
+       mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
+
        class->type_token = 0;
        /* all arrays are marked serializable and sealed, bug #42779 */
        class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED |
@@ -3718,62 +4015,16 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
 
        mono_class_setup_supertypes (class);
 
-       if (mono_defaults.generic_ilist_class) {
-               MonoClass *fclass = NULL;
-               int i;
-
-               if (eclass->valuetype) {
-                       if (eclass == mono_defaults.int16_class)
-                               fclass = mono_defaults.uint16_class;
-                       if (eclass == mono_defaults.uint16_class)
-                               fclass = mono_defaults.int16_class;
-                       if (eclass == mono_defaults.int32_class)
-                               fclass = mono_defaults.uint32_class;
-                       if (eclass == mono_defaults.uint32_class)
-                               fclass = mono_defaults.int32_class;
-                       if (eclass == mono_defaults.int64_class)
-                               fclass = mono_defaults.uint64_class;
-                       if (eclass == mono_defaults.uint64_class)
-                               fclass = mono_defaults.int64_class;
-                       if (eclass == mono_defaults.byte_class)
-                               fclass = mono_defaults.sbyte_class;
-                       if (eclass == mono_defaults.sbyte_class)
-                               fclass = mono_defaults.byte_class;
-
-                       class->interface_count = fclass ? 2 : 1;
-               } else if (MONO_CLASS_IS_INTERFACE (eclass)) {
-                       class->interface_count = 2 + eclass->interface_count;
-               } else {
-                       class->interface_count = eclass->idepth + eclass->interface_count;
-               }
+       if (mono_defaults.generic_ilist_class && !bounded && rank == 1) {
+               MonoType *args [1];
 
+               /* generic IList, ICollection, IEnumerable */
+               class->interface_count = 1;
                class->interfaces = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass*) * class->interface_count);
 
-               for (i = 0; i < class->interface_count; i++) {
-                       MonoType *args [1];
-                       MonoClass *iface;
-
-                       if (eclass->valuetype)
-                               iface = (i == 0) ? eclass : fclass;
-                       else if (MONO_CLASS_IS_INTERFACE (eclass)) {
-                               if (i == 0)
-                                       iface = mono_defaults.object_class;
-                               else if (i == 1)
-                                       iface = eclass;
-                               else
-                                       iface = eclass->interfaces [i - 2];
-                       } else {
-                               if (i < eclass->idepth)
-                                       iface = eclass->supertypes [i];
-                               else
-                                       iface = eclass->interfaces [i - eclass->idepth];
-                       }
-
-                       args [0] = &iface->byval_arg;
-
-                       class->interfaces [i] = mono_class_bind_generic_parameters (
-                               mono_defaults.generic_ilist_class, 1, args, FALSE);
-               }
+               args [0] = &eclass->byval_arg;
+               class->interfaces [0] = mono_class_bind_generic_parameters (
+                       mono_defaults.generic_ilist_class, 1, args, FALSE);
        }
 
        if (eclass->generic_class)
@@ -3815,6 +4066,8 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
 
        mono_loader_unlock ();
 
+       mono_profiler_class_loaded (class, MONO_PROFILE_OK);
+
        return class;
 }
 
@@ -4280,9 +4533,12 @@ mono_image_init_name_cache (MonoImage *image)
 
        for (i = 1; i <= t->rows; ++i) {
                mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
-               /* nested types are accessed from the nesting name */
                visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
-               if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
+               /*
+                * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
+                * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
+                */
+               if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
                        continue;
                name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
                nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
@@ -4419,9 +4675,12 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char
        /* add a cache if needed */
        for (i = 1; i <= t->rows; ++i) {
                mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
-               /* nested types are accessed from the nesting name */
                visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
-               if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
+               /*
+                * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
+                * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
+                */
+               if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
                        continue;
                n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
                nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
@@ -4878,7 +5137,8 @@ mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
                mono_class_init (class);
                return mono_class_get_field (class, token);
        }
-       case MONO_TOKEN_METHOD_DEF: {
+       case MONO_TOKEN_METHOD_DEF:
+       case MONO_TOKEN_METHOD_SPEC: {
                MonoMethod *meth;
                meth = mono_get_method_full (image, token, NULL, context);
                if (handle_class)
@@ -6009,3 +6269,9 @@ gboolean mono_class_is_valid_enum (MonoClass *klass) {
 
        return TRUE;
 }
+
+gboolean
+mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
+{
+       return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
+}