Sat Jan 8 19:03:26 CET 2005 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / class.c
index 8e820b2861aeae4938cf0a81c67f6cdb52285e00..361f4745a5a202d35722855b3f0868c33d5e4077 100644 (file)
@@ -154,16 +154,16 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
                        g_string_append (str, klass->name);
                if (is_recursed)
                        break;
-               if (klass->generic_inst) {
-                       MonoGenericInst *ginst = klass->generic_inst;
+               if (klass->generic_class) {
+                       MonoGenericClass *gclass = klass->generic_class;
                        int i;
 
                        g_string_append_c (str, '[');
-                       for (i = 0; i < ginst->type_argc; i++) {
+                       for (i = 0; i < gclass->inst->type_argc; i++) {
                                if (i)
                                        g_string_append_c (str, ',');
                                mono_type_get_name_recurse (
-                                       ginst->type_argv [i], str, FALSE, include_ns, include_arity);
+                                       gclass->inst->type_argv [i], str, FALSE, include_ns, include_arity);
                        }
                        g_string_append_c (str, ']');
                } else if (klass->generic_container) {
@@ -181,11 +181,11 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
        }
 }
 
-/*
+/**
  * mono_type_get_name:
  * @type: a type
  *
- * Returns the string representation for type as required by System.Reflection.
+ * Returns: the string representation for type as required by System.Reflection.
  * The inverse of mono_reflection_parse_type ().
  */
 static char*
@@ -222,7 +222,7 @@ mono_type_get_underlying_type (MonoType *type)
                        return type->data.klass->enum_basetype;
                break;
        case MONO_TYPE_GENERICINST:
-               return mono_type_get_underlying_type (type->data.generic_inst->generic_type);
+               return mono_type_get_underlying_type (&type->data.generic_class->container_class->byval_arg);
        default:
                break;
        }
@@ -244,13 +244,13 @@ mono_class_is_open_constructed_type (MonoType *t)
        case MONO_TYPE_PTR:
                return mono_class_is_open_constructed_type (t->data.type);
        case MONO_TYPE_GENERICINST: {
-               MonoGenericInst *ginst = t->data.generic_inst;
+               MonoGenericClass *gclass = t->data.generic_class;
                int i;
 
-               if (mono_class_is_open_constructed_type (ginst->generic_type))
+               if (mono_class_is_open_constructed_type (&gclass->container_class->byval_arg))
                        return TRUE;
-               for (i = 0; i < ginst->type_argc; i++)
-                       if (mono_class_is_open_constructed_type (ginst->type_argv [i]))
+               for (i = 0; i < gclass->inst->type_argc; i++)
+                       if (mono_class_is_open_constructed_type (gclass->inst->type_argv [i]))
                                return TRUE;
                return FALSE;
        }
@@ -259,21 +259,59 @@ mono_class_is_open_constructed_type (MonoType *t)
        }
 }
 
+static MonoGenericClass *
+inflate_generic_class (MonoGenericClass *ogclass, MonoGenericContext *context)
+{
+       MonoGenericClass *ngclass, *cached;
+
+       if (ogclass->is_dynamic) {
+               MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
+               ngclass = &dgclass->generic_class;
+               ngclass->is_dynamic = 1;
+       } else
+               ngclass = g_new0 (MonoGenericClass, 1);
+
+       *ngclass = *ogclass;
+
+       ngclass->inst = mono_metadata_inflate_generic_inst (ogclass->inst, context);
+
+       ngclass->klass = NULL;
+
+       ngclass->context = g_new0 (MonoGenericContext, 1);
+       ngclass->context->container = context->container;
+       ngclass->context->gclass = ngclass;
+
+       ngclass->initialized = FALSE;
+
+       mono_loader_lock ();
+       cached = mono_metadata_lookup_generic_class (ngclass);
+       mono_loader_unlock ();
+       if (cached) {
+               g_free (ngclass);
+               return cached;
+       }
+
+       mono_class_create_generic (ngclass);
+       mono_class_create_generic_2 (ngclass);
+
+       return ngclass;
+}
+
 static MonoType*
 inflate_generic_type (MonoType *type, MonoGenericContext *context)
 {
        switch (type->type) {
        case MONO_TYPE_MVAR:
-               if (context->gmethod && context->gmethod->mtype_argv)
+               if (context->gmethod && context->gmethod->inst->type_argv)
                        return dup_type (
-                               context->gmethod->mtype_argv [type->data.generic_param->num],
+                               context->gmethod->inst->type_argv [type->data.generic_param->num],
                                type);
                else
                        return NULL;
        case MONO_TYPE_VAR:
-               if (context->ginst)
+               if (context->gclass)
                        return dup_type (
-                               context->ginst->type_argv [type->data.generic_param->num],
+                               context->gclass->inst->type_argv [type->data.generic_param->num],
                                type);
                else
                        return NULL;
@@ -287,59 +325,25 @@ inflate_generic_type (MonoType *type, MonoGenericContext *context)
                return nt;
        }
        case MONO_TYPE_GENERICINST: {
-               MonoGenericInst *oginst = type->data.generic_inst;
-               MonoGenericInst *nginst, *cached;
+               MonoGenericClass *ngclass = inflate_generic_class (type->data.generic_class, context);
+               MonoType *nt = dup_type (type, type);
+               nt->data.generic_class = ngclass;
+               return nt;
+       }
+       case MONO_TYPE_CLASS:
+       case MONO_TYPE_VALUETYPE: {
+               MonoClass *klass = type->data.klass;
+               MonoGenericClass *gclass;
                MonoType *nt;
-               int i;
-
-               nginst = g_new0 (MonoGenericInst, 1);
-               *nginst = *oginst;
-
-               nginst->is_open = FALSE;
-
-               nginst->type_argv = g_new0 (MonoType *, oginst->type_argc);
-
-               for (i = 0; i < oginst->type_argc; i++) {
-                       MonoType *t = oginst->type_argv [i];
-                       nginst->type_argv [i] = mono_class_inflate_generic_type (t, context);
-
-                       if (!nginst->is_open)
-                               nginst->is_open = mono_class_is_open_constructed_type (nginst->type_argv [i]);
-               };
 
-               nginst->klass = NULL;
-
-               nginst->context = g_new0 (MonoGenericContext, 1);
-               nginst->context->ginst = nginst;
-
-               mono_loader_lock ();
-               cached = g_hash_table_lookup (oginst->klass->image->generic_inst_cache, nginst);
-
-               if (cached) {
-                       g_free (nginst->type_argv);
-                       g_free (nginst);
-                       mono_loader_unlock ();
-
-                       nt = dup_type (type, type);
-                       nt->data.generic_inst = cached;
-                       return nt;
-               }
-
-               nginst->dynamic_info = NULL;
-               nginst->initialized = FALSE;
-
-               mono_class_create_generic (nginst);
-               mono_class_create_generic_2 (nginst);
+               if (!klass->generic_container)
+                       return NULL;
 
-               mono_stats.generic_instance_count++;
-               mono_stats.generics_metadata_size += sizeof (MonoGenericInst) +
-                       sizeof (MonoGenericContext) +
-                       nginst->type_argc * sizeof (MonoType);
+               gclass = inflate_generic_class (klass->generic_container->context.gclass, context);
 
                nt = dup_type (type, type);
-               nt->data.generic_inst = nginst;
-               g_hash_table_insert (oginst->klass->image->generic_inst_cache, nginst, nginst);
-               mono_loader_unlock ();
+               nt->type = MONO_TYPE_GENERICINST;
+               nt->data.generic_class = gclass;
                return nt;
        }
        default:
@@ -354,20 +358,22 @@ mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
        MonoType *inflated = inflate_generic_type (type, context);
 
        if (!inflated)
-               return type;
+               return dup_type (type, type);
 
        mono_stats.inflated_type_count++;
        return inflated;
 }
 
-static MonoMethodSignature*
-inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig,
-                          MonoGenericContext *context)
+MonoMethodSignature*
+mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericContext *context)
 {
        MonoMethodSignature *res;
        gboolean is_open;
        int i;
 
+       if (!context)
+               return sig;
+
        res = mono_metadata_signature_alloc (image, sig->param_count);
        res->ret = mono_class_inflate_generic_type (sig->ret, context);
        is_open = mono_class_is_open_constructed_type (res->ret);
@@ -380,6 +386,7 @@ inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig,
        res->explicit_this = sig->explicit_this;
        res->call_convention = sig->call_convention;
        res->generic_param_count = sig->generic_param_count;
+       res->sentinelpos = sig->sentinelpos;
        res->has_type_parameters = is_open;
        res->is_inflated = 1;
        return res;
@@ -403,6 +410,27 @@ inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context)
        return res;
 }
 
+static MonoGenericContext *
+inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with)
+{
+       MonoGenericContext *res = g_new0 (MonoGenericContext, 1);
+
+       res->container = context->container;
+
+       if (context->gclass)
+               res->gclass = inflate_generic_class (context->gclass, inflate_with);
+
+       if (context->gmethod) {
+               res->gmethod = g_new0 (MonoGenericMethod, 1);
+
+               res->gmethod->container = context->gmethod->container;
+               res->gmethod->inst = mono_metadata_inflate_generic_inst (context->gmethod->inst, inflate_with);
+       } else
+               res->gmethod = inflate_with->gmethod;
+
+       return res;
+}
+
 MonoMethod*
 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context,
                                   MonoClass *klass)
@@ -414,42 +442,61 @@ mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *conte
            (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
                return method;
 
+       if (method->is_inflated || method->signature->is_inflated) {
+               MonoMethodInflated *imethod = (MonoMethodInflated *) method;
+
+               context = inflate_generic_context (imethod->context, context);
+               method = imethod->declaring;
+       }
+
        mono_stats.inflated_method_count++;
-       mono_stats.generics_metadata_size +=
-               sizeof (MonoMethodInflated) - sizeof (MonoMethodNormal);
 
        result = g_new0 (MonoMethodInflated, 1);
        result->nmethod = *(MonoMethodNormal*)method;
+       result->nmethod.method.is_inflated = 1;
+       result->context = context;
+       result->declaring = method;
 
-       if (mono_method_get_header (method))
-               result->nmethod.header = inflate_generic_header (
-                       mono_method_get_header (method), context);
+       if (result->nmethod.method.klass->generic_class)
+               result->nmethod.method.klass = result->nmethod.method.klass->generic_class->container_class;
 
-       if (klass)
-               rklass = result->nmethod.method.klass = klass;
-       else {
-               MonoType *declaring = mono_class_inflate_generic_type (&method->klass->byval_arg, context);
-               rklass = result->nmethod.method.klass = mono_class_from_mono_type (declaring);
-       }
+       return (MonoMethod *) result;
+}
 
-       result->nmethod.method.signature = inflate_generic_signature (
-               method->klass->image, method->signature, context);
+MonoMethod *
+mono_get_inflated_method (MonoMethod *method)
+{
+       MonoMethodInflated *imethod, *res;
+       MonoMethodHeader *mh;
+       MonoType *dtype;
+       MonoClass *rklass;
 
-       if (context->gmethod) {
-               result->context = g_new0 (MonoGenericContext, 1);
-               result->context->gmethod = context->gmethod;
-               result->context->ginst = rklass->generic_inst;
+       if (!method->is_inflated)
+               return method;
 
-               mono_stats.generics_metadata_size += sizeof (MonoGenericContext);
-       } else if (rklass->generic_inst)
-               result->context = rklass->generic_inst->context;
+       imethod = (MonoMethodInflated *) method;
+       if (imethod->inflated)
+               return (MonoMethod *) imethod->inflated;
 
-       if (method->signature->is_inflated)
-               result->declaring = ((MonoMethodInflated *) method)->declaring;
-       else
-               result->declaring = method;
+       mono_stats.inflated_method_count_2++;
+       mono_stats.generics_metadata_size +=
+               sizeof (MonoMethodInflated) - sizeof (MonoMethodNormal);
 
-       return (MonoMethod *) result;
+       res = g_new0 (MonoMethodInflated, 1);
+       *res = *imethod;
+       res->inflated = imethod->inflated = res;
+
+       mh = mono_method_get_header (method);
+       if (mh)
+               res->nmethod.header = inflate_generic_header (mh, imethod->context);
+
+       dtype = mono_class_inflate_generic_type (&method->klass->byval_arg, imethod->context);
+       rklass = res->nmethod.method.klass = mono_class_from_mono_type (dtype);
+
+       res->nmethod.method.signature = mono_class_inflate_generic_signature (
+               method->klass->image, method->signature, imethod->context);
+
+       return (MonoMethod *) res;
 }
 
 /** 
@@ -531,17 +578,18 @@ class_compute_field_layout (MonoClass *class)
                g_assert (*sig == 0x06);
                if (class->generic_container)
                        container = class->generic_container;
-               else if (class->generic_inst) {
-                       g_assert (class->generic_inst->container);
-                       container = class->generic_inst->container;
+               else if (class->generic_class) {
+                       container = class->generic_class->container_class->generic_container;
+                       g_assert (container);
                }
                field->type = mono_metadata_parse_type_full (
-                       m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
+                       m, (MonoGenericContext *) container, MONO_PARSE_FIELD,
+                       cols [MONO_FIELD_FLAGS], sig + 1, &sig);
                if (mono_field_is_deleted (field))
                        continue;
-               if (class->generic_inst) {
+               if (class->generic_class) {
                        field->type = mono_class_inflate_generic_type (
-                               field->type, class->generic_inst->context);
+                               field->type, class->generic_class->context);
                        field->type->attrs = cols [MONO_FIELD_FLAGS];
                }
 
@@ -594,7 +642,7 @@ class_compute_field_layout (MonoClass *class)
        }
 
        if (class->generic_container ||
-           (class->generic_inst && class->generic_inst->is_open))
+           (class->generic_class && class->generic_class->inst->is_open))
                return;
 
        mono_class_layout_fields (class);
@@ -975,7 +1023,7 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum)
        MonoMethod **vtable;
        int i, max_vtsize = 0, max_iid, cur_slot = 0;
        GPtrArray *ifaces;
-       MonoGHashTable *override_map = NULL;
+       GHashTable *override_map = NULL;
 
        /* setup_vtable() must be called only once on the type */
        if (class->interface_offsets) {
@@ -1020,9 +1068,9 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum)
                        vtable [dslot] = overrides [i*2 + 1];
                        vtable [dslot]->slot = dslot;
                        if (!override_map)
-                               override_map = mono_g_hash_table_new (NULL, NULL);
+                               override_map = g_hash_table_new (NULL, NULL);
 
-                       mono_g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
+                       g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
                }
        }
 
@@ -1105,8 +1153,8 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum)
                                if (vtable [io + l])
                                        continue;
 
-                               if (ic->generic_inst) {
-                                       MonoClass *the_ic = mono_class_from_mono_type (ic->generic_inst->generic_type);
+                               if (ic->generic_class) {
+                                       MonoClass *the_ic = ic->generic_class->container_class;
                                        the_cname = _mono_type_get_name (&the_ic->byval_arg, TRUE, FALSE, TRUE);
                                        cname = the_cname;
                                } else {
@@ -1229,8 +1277,8 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum)
                                                slot = k->methods [j]->slot;
                                                g_assert (cm->slot < max_vtsize);
                                                if (!override_map)
-                                                       override_map = mono_g_hash_table_new (NULL, NULL);
-                                               mono_g_hash_table_insert (override_map, m1, cm);
+                                                       override_map = g_hash_table_new (NULL, NULL);
+                                               g_hash_table_insert (override_map, m1, cm);
                                                break;
                                        }
                                }
@@ -1256,8 +1304,8 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum)
                        vtable [decl->slot] = overrides [i*2 + 1];
                        overrides [i * 2 + 1]->slot = decl->slot;
                        if (!override_map)
-                               override_map = mono_g_hash_table_new (NULL, NULL);
-                       mono_g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
+                               override_map = g_hash_table_new (NULL, NULL);
+                       g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
                }
        }
 
@@ -1268,16 +1316,16 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum)
        if (override_map) {
                for (i = 0; i < max_vtsize; ++i)
                        if (vtable [i]) {
-                               MonoMethod *cm = mono_g_hash_table_lookup (override_map, vtable [i]);
+                               MonoMethod *cm = g_hash_table_lookup (override_map, vtable [i]);
                                if (cm)
                                        vtable [i] = cm;
                        }
 
-               mono_g_hash_table_destroy (override_map);
+               g_hash_table_destroy (override_map);
        }
 
-       if (class->generic_inst) {
-               MonoClass *gklass = mono_class_from_mono_type (class->generic_inst->generic_type);
+       if (class->generic_class) {
+               MonoClass *gklass = class->generic_class->container_class;
 
                mono_class_init (gklass);
                class->vtable_size = gklass->vtable_size;
@@ -1380,11 +1428,12 @@ mono_class_init (MonoClass *class)
 
        mono_stats.initialized_class_count++;
 
-       if (class->generic_inst && !class->generic_inst->is_dynamic) {
-               MonoGenericInst *ginst = class->generic_inst;
-               MonoClass *gklass;
+       if (class->generic_class && !class->generic_class->is_dynamic) {
+               MonoGenericClass *gclass = class->generic_class;
+               MonoClass *gklass = gclass->container_class;
+
+               mono_stats.generic_class_count++;
 
-               gklass = mono_class_from_mono_type (ginst->generic_type);
                mono_class_init (gklass);
 
                if (MONO_CLASS_IS_INTERFACE (class))
@@ -1393,9 +1442,12 @@ mono_class_init (MonoClass *class)
                g_assert (class->method.count == gklass->method.count);
                class->methods = g_new0 (MonoMethod *, class->method.count);
 
-               for (i = 0; i < class->method.count; i++)
-                       class->methods [i] = mono_class_inflate_generic_method (
-                               gklass->methods [i], ginst->context, ginst->klass);
+               for (i = 0; i < class->method.count; i++) {
+                       MonoMethod *inflated = mono_class_inflate_generic_method (
+                               gklass->methods [i], gclass->context, gclass->klass);
+
+                       class->methods [i] = mono_get_inflated_method (inflated);
+               }
 
                g_assert (class->field.count == gklass->field.count);
                class->fields = g_new0 (MonoClassField, class->field.count);
@@ -1408,7 +1460,7 @@ mono_class_init (MonoClass *class)
                        class->fields [i].generic_info = ifield;
                        class->fields [i].parent = class;
                        class->fields [i].type = mono_class_inflate_generic_type (
-                               class->fields [i].type, ginst->context);
+                               class->fields [i].type, gclass->context);
                }
 
                class->property = gklass->property;
@@ -1421,10 +1473,10 @@ mono_class_init (MonoClass *class)
 
                        if (prop->get)
                                prop->get = mono_class_inflate_generic_method (
-                                       prop->get, ginst->context, ginst->klass);
+                                       prop->get, gclass->context, gclass->klass);
                        if (prop->set)
                                prop->set = mono_class_inflate_generic_method (
-                                       prop->set, ginst->context, ginst->klass);
+                                       prop->set, gclass->context, gclass->klass);
 
                        prop->parent = class;
                }
@@ -1478,7 +1530,7 @@ mono_class_init (MonoClass *class)
                        class->methods [1] = ctor;
                }
        } else {
-               if (!class->generic_inst && !class->methods) {
+               if (!class->generic_class && !class->methods) {
                        class->methods = g_new (MonoMethod*, class->method.count);
                        for (i = 0; i < class->method.count; ++i) {
                                class->methods [i] = mono_get_method (class->image,
@@ -1487,7 +1539,7 @@ mono_class_init (MonoClass *class)
                }
        }
 
-       if (!class->generic_inst) {
+       if (!class->generic_class) {
                init_properties (class);
                init_events (class);
 
@@ -1731,7 +1783,7 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
                if (!parent)
                        g_assert_not_reached (); /* FIXME */
 
-               if (parent->generic_inst && !parent->name) {
+               if (parent->generic_class && !parent->name) {
                        /*
                         * If the parent is a generic instance, we may get
                         * called before it is fully initialized, especially
@@ -1816,6 +1868,59 @@ set_generic_param_owner (MonoGenericContainer *container, MonoClass *klass, int
        return pos + gc->type_argc;
 }
 
+static MonoGenericInst *
+get_shared_inst (MonoGenericContainer *container)
+{
+       MonoGenericInst *nginst;
+       int i;
+
+       nginst = g_new0 (MonoGenericInst, 1);
+       nginst->type_argc = container->type_argc;
+       nginst->type_argv = g_new0 (MonoType *, nginst->type_argc);
+       nginst->is_open = 1;
+
+       for (i = 0; i < nginst->type_argc; i++) {
+               MonoType *t = g_new0 (MonoType, 1);
+
+               t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
+               t->data.generic_param = &container->type_params [i];
+
+               nginst->type_argv [i] = t;
+       }
+
+       return mono_metadata_lookup_generic_inst (nginst);
+}
+
+MonoGenericClass *
+mono_get_shared_generic_class (MonoGenericContainer *container, gboolean is_dynamic)
+{
+       MonoGenericClass *gclass;
+       MonoGenericClass *cached;
+
+       if (is_dynamic) {
+               MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
+               gclass = &dgclass->generic_class;
+               gclass->is_dynamic = 1;
+       } else
+               gclass = g_new0 (MonoGenericClass, 1);
+
+       gclass->context = &container->context;
+       gclass->container_class = container->klass;
+       gclass->inst = get_shared_inst (container);
+
+#if 0
+       cached = mono_metadata_lookup_generic_class (gclass);
+       if (cached) {
+               g_free (gclass);
+               return cached;
+       }
+#endif
+
+       gclass->klass = container->klass;
+
+       return gclass;
+}
+
 /**
  * @image: context where the image is created
  * @type_token:  typedef token
@@ -1858,16 +1963,22 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 
        g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
 
-       class->generic_container = mono_metadata_load_generic_params (image, class->type_token);
+       class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
        if (class->generic_container) {
                class->generic_container->klass = class;
-               context = g_new0 (MonoGenericContext, 1);
-               context->container = class->generic_container;
+               context = &class->generic_container->context;
+
+               context->gclass = mono_get_shared_generic_class (context->container, FALSE);
        }
 
        if (cols [MONO_TYPEDEF_EXTENDS])
                parent = mono_class_get_full (
                        image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
+
+       mono_class_setup_parent (class, parent);
+
+       mono_class_setup_mono_type (class);
+
        interfaces = mono_metadata_interfaces_from_typedef_full (image, type_token, &icount, context);
 
        class->interfaces = interfaces;
@@ -1884,10 +1995,6 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 
        /*g_print ("Load class %s\n", name);*/
 
-       mono_class_setup_parent (class, parent);
-
-       mono_class_setup_mono_type (class);
-
        /*
         * Compute the field and method lists
         */
@@ -1935,15 +2042,15 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 }
 
 void
-mono_class_create_generic (MonoGenericInst *ginst)
+mono_class_create_generic (MonoGenericClass *gclass)
 {
        MonoClass *klass, *gklass;
 
-       if (!ginst->klass)
-               ginst->klass = g_malloc0 (sizeof (MonoClass));
-       klass = ginst->klass;
+       if (!gclass->klass)
+               gclass->klass = g_malloc0 (sizeof (MonoClass));
+       klass = gclass->klass;
 
-       gklass = mono_class_from_mono_type (ginst->generic_type);
+       gklass = gclass->container_class;
 
        klass->nested_in = gklass->nested_in;
 
@@ -1952,36 +2059,38 @@ mono_class_create_generic (MonoGenericInst *ginst)
        klass->image = gklass->image;
        klass->flags = gklass->flags;
 
-       klass->generic_inst = ginst;
+       klass->generic_class = gclass;
 
        klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
-       klass->this_arg.data.generic_inst = klass->byval_arg.data.generic_inst = ginst;
+       klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
        klass->this_arg.byref = TRUE;
 
        klass->cast_class = klass->element_class = klass;
 
-       if (ginst->is_dynamic) {
+       if (gclass->is_dynamic) {
                klass->instance_size = gklass->instance_size;
                klass->class_size = gklass->class_size;
                klass->size_inited = 1;
                klass->inited = 1;
 
                klass->valuetype = gklass->valuetype;
+
+               mono_class_setup_supertypes (klass);
        }
 }
 
 void
-mono_class_create_generic_2 (MonoGenericInst *ginst)
+mono_class_create_generic_2 (MonoGenericClass *gclass)
 {
        MonoClass *klass, *gklass;
        GList *list;
        int i;
 
-       if (ginst->is_dynamic)
+       if (gclass->is_dynamic)
                return;
 
-       klass = ginst->klass;
-       gklass = mono_class_from_mono_type (ginst->generic_type);
+       klass = gclass->klass;
+       gklass = gclass->container_class;
 
        klass->method = gklass->method;
        klass->field = gklass->field;
@@ -1990,7 +2099,7 @@ mono_class_create_generic_2 (MonoGenericInst *ginst)
        klass->interfaces = g_new0 (MonoClass *, klass->interface_count);
        for (i = 0; i < klass->interface_count; i++) {
                MonoType *it = &gklass->interfaces [i]->byval_arg;
-               MonoType *inflated = mono_class_inflate_generic_type (it, ginst->context);
+               MonoType *inflated = mono_class_inflate_generic_type (it, gclass->context);
                klass->interfaces [i] = mono_class_from_mono_type (inflated);
        }
 
@@ -1998,10 +2107,10 @@ mono_class_create_generic_2 (MonoGenericInst *ginst)
                klass->nested_classes = g_list_append (
                        klass->nested_classes, list->data);
 
-       if (ginst->parent)
-               klass->parent = mono_class_from_mono_type (ginst->parent);
+       if (gclass->parent)
+               klass->parent = mono_class_from_mono_type (gclass->parent);
        else if (gklass->parent) {
-               MonoType *inflated = mono_class_inflate_generic_type (&gklass->parent->byval_arg, ginst->context);
+               MonoType *inflated = mono_class_inflate_generic_type (&gklass->parent->byval_arg, gclass->context);
 
                klass->parent = mono_class_from_mono_type (inflated);
        }
@@ -2223,8 +2332,8 @@ mono_class_from_mono_type (MonoType *type)
        case MONO_TYPE_VALUETYPE:
                return type->data.klass;
        case MONO_TYPE_GENERICINST:
-               g_assert (type->data.generic_inst->klass);
-               return type->data.generic_inst->klass;
+               g_assert (type->data.generic_class->klass);
+               return type->data.generic_class->klass;
        case MONO_TYPE_VAR:
                return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE);
        case MONO_TYPE_MVAR:
@@ -2246,21 +2355,9 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec,
                                 MonoGenericContext *context)
 {
        MonoType *type, *inflated;
-       MonoGenericContainer *container = NULL;
        MonoClass *class;
 
-       if (context) {
-               if (context->gmethod && context->gmethod->container) {
-                       g_assert (context->gmethod->container);
-                       container = context->gmethod->container;
-               } else if (context->ginst) {
-                       g_assert (context->ginst->container);
-                       container = context->ginst->container;
-               } else if (context->container)
-                       container = context->container;
-       }
-
-       type = mono_type_create_from_typespec_full (image, container, type_spec);
+       type = mono_type_create_from_typespec_full (image, context, type_spec);
 
        switch (type->type) {
        case MONO_TYPE_ARRAY:
@@ -2273,8 +2370,8 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec,
                class = mono_ptr_class_get (type->data.type);
                break;
        case MONO_TYPE_GENERICINST:
-               g_assert (type->data.generic_inst->klass);
-               class = type->data.generic_inst->klass;
+               g_assert (type->data.generic_class->klass);
+               class = type->data.generic_class->klass;
                break;
        default:
                /* it seems any type can be stored in TypeSpec as well */
@@ -2282,7 +2379,7 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec,
                break;
        }
 
-       if (!class || !context)
+       if (!class || !context || (!context->gclass && !context->gmethod))
                return class;
 
        inflated = mono_class_inflate_generic_type (&class->byval_arg, context);
@@ -2423,7 +2520,7 @@ mono_class_instance_size (MonoClass *klass)
                mono_class_init (klass);
 
        g_assert (!klass->generic_container &&
-                 (!klass->generic_inst || !klass->generic_inst->is_open));
+                 (!klass->generic_class || !klass->generic_class->inst->is_open));
        return klass->instance_size;
 }
 
@@ -2662,12 +2759,12 @@ mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *c
        MonoClass *class = _mono_class_get (image, type_token, context);
        MonoType *inflated;
 
-       if (!class || !context || (!context->ginst && !context->gmethod))
+       if (!class || !context || (!context->gclass && !context->gmethod))
                return class;
 
        switch (class->byval_arg.type) {
        case MONO_TYPE_GENERICINST:
-               if (!class->generic_inst->is_open)
+               if (!class->generic_class->inst->is_open)
                        return class;
                break;
        case MONO_TYPE_VAR:
@@ -2830,6 +2927,7 @@ mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
                           gboolean check_interfaces)
 {
  again:
+       g_assert (klassc->idepth > 0);
        if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
                if ((klassc->interface_id <= klass->max_interface_id) &&
                        (klass->interface_offsets [klassc->interface_id] >= 0))
@@ -2854,8 +2952,8 @@ mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
        if (klassc == mono_defaults.object_class)
                return TRUE;
 
-       if (klass->generic_inst) {
-               MonoType *parent = klass->generic_inst->parent;
+       if (klass->generic_class) {
+               MonoType *parent = klass->generic_class->parent;
                if (!parent)
                        return FALSE;
 
@@ -2941,8 +3039,11 @@ mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
        return FALSE;
 }
 
-/*
- * Returns the nnumber of bytes an element of type klass
+/**
+ * mono_class_array_element_size:
+ * @klass: 
+ *
+ * Returns: the number of bytes an element of type @klass
  * uses when stored into an array.
  */
 gint32
@@ -2987,7 +3088,7 @@ handle_enum:
                }
                return mono_class_instance_size (klass) - sizeof (MonoObject);
        case MONO_TYPE_GENERICINST:
-               type = type->data.generic_inst->generic_type;
+               type = &type->data.generic_class->container_class->byval_arg;
                goto handle_enum;
        default:
                g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
@@ -3125,7 +3226,7 @@ mono_class_get_image (MonoClass *klass)
  * mono_class_get_element_class:
  * @klass: the MonoClass to act on
  *
- * Returns the element class of an array or an enumeration.
+ * Returns: the element class of an array or an enumeration.
  */
 MonoClass*
 mono_class_get_element_class (MonoClass *klass)
@@ -3137,7 +3238,7 @@ mono_class_get_element_class (MonoClass *klass)
  * mono_class_is_valuetype:
  * @klass: the MonoClass to act on
  *
- * Returns true if the MonoClass represents a ValueType.
+ * Returns: true if the MonoClass represents a ValueType.
  */
 gboolean
 mono_class_is_valuetype (MonoClass *klass)
@@ -3149,7 +3250,7 @@ mono_class_is_valuetype (MonoClass *klass)
  * mono_class_is_enum:
  * @klass: the MonoClass to act on
  *
- * Returns true if the MonoClass represents an enumeration.
+ * Returns: true if the MonoClass represents an enumeration.
  */
 gboolean
 mono_class_is_enum (MonoClass *klass)
@@ -3161,7 +3262,7 @@ mono_class_is_enum (MonoClass *klass)
  * mono_class_enum_basetype:
  * @klass: the MonoClass to act on
  *
- * Returns the underlying type representation for an enumeration.
+ * Returns: the underlying type representation for an enumeration.
  */
 MonoType*
 mono_class_enum_basetype (MonoClass *klass)
@@ -3173,7 +3274,7 @@ mono_class_enum_basetype (MonoClass *klass)
  * mono_class_get_parent
  * @klass: the MonoClass to act on
  *
- * Returns the parent class for this class.
+ * Returns: the parent class for this class.
  */
 MonoClass*
 mono_class_get_parent (MonoClass *klass)
@@ -3185,7 +3286,7 @@ mono_class_get_parent (MonoClass *klass)
  * mono_class_get_nesting_type;
  * @klass: the MonoClass to act on
  *
- * Returns the container type where this type is nested or NULL if this type is not a nested type.
+ * Returns: the container type where this type is nested or NULL if this type is not a nested type.
  */
 MonoClass*
 mono_class_get_nesting_type (MonoClass *klass)
@@ -3197,7 +3298,7 @@ mono_class_get_nesting_type (MonoClass *klass)
  * mono_class_get_rank:
  * @klass: the MonoClass to act on
  *
- * Returns the rank for the array (the number of dimensions).
+ * Returns: the rank for the array (the number of dimensions).
  */
 int
 mono_class_get_rank (MonoClass *klass)
@@ -3213,7 +3314,7 @@ mono_class_get_rank (MonoClass *klass)
  * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
  * different values.
  *
- * Returns the flags from the TypeDef table.
+ * Returns: the flags from the TypeDef table.
  */
 guint32
 mono_class_get_flags (MonoClass *klass)
@@ -3225,7 +3326,7 @@ mono_class_get_flags (MonoClass *klass)
  * mono_class_get_name
  * @klass: the MonoClass to act on
  *
- * Returns the name of the class.
+ * Returns: the name of the class.
  */
 const char*
 mono_class_get_name (MonoClass *klass)
@@ -3237,7 +3338,7 @@ mono_class_get_name (MonoClass *klass)
  * mono_class_get_namespace:
  * @klass: the MonoClass to act on
  *
- * Returns the namespace of the class.
+ * Returns: the namespace of the class.
  */
 const char*
 mono_class_get_namespace (MonoClass *klass)
@@ -3251,7 +3352,7 @@ mono_class_get_namespace (MonoClass *klass)
  *
  * This method returns the internal Type representation for the class.
  *
- * Returns the MonoType from the class.
+ * Returns: the MonoType from the class.
  */
 MonoType*
 mono_class_get_type (MonoClass *klass)
@@ -3275,7 +3376,7 @@ mono_class_get_byref_type (MonoClass *klass)
  * mono_class_num_fields:
  * @klass: the MonoClass to act on
  *
- * Returns the number of static and instance fields in the class.
+ * Returns: the number of static and instance fields in the class.
  */
 int
 mono_class_num_fields (MonoClass *klass)
@@ -3287,7 +3388,7 @@ mono_class_num_fields (MonoClass *klass)
  * mono_class_num_methods:
  * @klass: the MonoClass to act on
  *
- * Returns the number of methods in the class.
+ * Returns: the number of methods in the class.
  */
 int
 mono_class_num_methods (MonoClass *klass)
@@ -3299,7 +3400,7 @@ mono_class_num_methods (MonoClass *klass)
  * mono_class_num_properties
  * @klass: the MonoClass to act on
  *
- * Returns the number of properties in the class.
+ * Returns: the number of properties in the class.
  */
 int
 mono_class_num_properties (MonoClass *klass)
@@ -3311,7 +3412,7 @@ mono_class_num_properties (MonoClass *klass)
  * mono_class_num_events:
  * @klass: the MonoClass to act on
  *
- * Returns the number of events in the class.
+ * Returns: the number of events in the class.
  */
 int
 mono_class_num_events (MonoClass *klass)
@@ -3366,7 +3467,7 @@ mono_class_get_fields (MonoClass* klass, gpointer *iter)
  * iterate over all of the elements.  When no more values are
  * available, the return value is NULL.
  *
- * Returns a MonoMethod on each iteration or NULL when no more methods are available.
+ * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
  */
 MonoMethod*
 mono_class_get_methods (MonoClass* klass, gpointer *iter)
@@ -3551,7 +3652,7 @@ mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
  * mono_field_get_name:
  * @field: the MonoClassField to act on
  *
- * Returns the name of the field.
+ * Returns: the name of the field.
  */
 const char*
 mono_field_get_name (MonoClassField *field)
@@ -3563,7 +3664,7 @@ mono_field_get_name (MonoClassField *field)
  * mono_field_get_type:
  * @field: the MonoClassField to act on
  *
- * Returns MonoType of the field.
+ * Returns: MonoType of the field.
  */
 MonoType*
 mono_field_get_type (MonoClassField *field)
@@ -3575,7 +3676,7 @@ mono_field_get_type (MonoClassField *field)
  * mono_field_get_type:
  * @field: the MonoClassField to act on
  *
- * Returns MonoClass where the field was defined.
+ * Returns: MonoClass where the field was defined.
  */
 MonoClass*
 mono_field_get_parent (MonoClassField *field)
@@ -3590,7 +3691,7 @@ mono_field_get_parent (MonoClassField *field)
  * The metadata flags for a field are encoded using the
  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
  *
- * Returns the flags for the field.
+ * Returns: the flags for the field.
  */
 guint32
 mono_field_get_flags (MonoClassField *field)
@@ -3602,7 +3703,7 @@ mono_field_get_flags (MonoClassField *field)
  * mono_property_get_name: 
  * @prop: the MonoProperty to act on
  *
- * Returns the name of the property
+ * Returns: the name of the property
  */
 const char*
 mono_property_get_name (MonoProperty *prop)
@@ -3614,7 +3715,7 @@ mono_property_get_name (MonoProperty *prop)
  * mono_property_get_set_method
  * @prop: the MonoProperty to act on.
  *
- * Returns the setter method of the property (A MonoMethod)
+ * Returns: the setter method of the property (A MonoMethod)
  */
 MonoMethod*
 mono_property_get_set_method (MonoProperty *prop)
@@ -3626,7 +3727,7 @@ mono_property_get_set_method (MonoProperty *prop)
  * mono_property_get_get_method
  * @prop: the MonoProperty to act on.
  *
- * Returns the setter method of the property (A MonoMethod)
+ * Returns: the setter method of the property (A MonoMethod)
  */
 MonoMethod*
 mono_property_get_get_method (MonoProperty *prop)
@@ -3638,7 +3739,7 @@ mono_property_get_get_method (MonoProperty *prop)
  * mono_property_get_parent:
  * @prop: the MonoProperty to act on.
  *
- * Returns the MonoClass where the property was defined.
+ * Returns: the MonoClass where the property was defined.
  */
 MonoClass*
 mono_property_get_parent (MonoProperty *prop)
@@ -3653,7 +3754,7 @@ mono_property_get_parent (MonoProperty *prop)
  * The metadata flags for a property are encoded using the
  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
  *
- * Returns the flags for the property.
+ * Returns: the flags for the property.
  */
 guint32
 mono_property_get_flags (MonoProperty *prop)
@@ -3665,7 +3766,7 @@ mono_property_get_flags (MonoProperty *prop)
  * mono_event_get_name:
  * @event: the MonoEvent to act on
  *
- * Returns the name of the event.
+ * Returns: the name of the event.
  */
 const char*
 mono_event_get_name (MonoEvent *event)
@@ -3713,7 +3814,7 @@ mono_event_get_raise_method (MonoEvent *event)
  * mono_event_get_parent:
  * @event: the MonoEvent to act on.
  *
- * Returns the MonoClass where the event is defined.
+ * Returns: the MonoClass where the event is defined.
  */
 MonoClass*
 mono_event_get_parent (MonoEvent *event)
@@ -3728,7 +3829,7 @@ mono_event_get_parent (MonoEvent *event)
  * The metadata flags for an event are encoded using the
  * EVENT_* constants.  See the tabledefs.h file for details.
  *
- * Returns the flags for the event.
+ * Returns: the flags for the event.
  */
 guint32
 mono_event_get_flags (MonoEvent *event)