Revert patch as it introduced a regression while building: ** ERROR **: file metadat...
[mono.git] / mono / metadata / class.c
index 2fbf86f286b0e8873821121e91cf55d3cca2aa6d..f8fb5f366d850bcddc3306561991943c44645cc8 100644 (file)
@@ -41,7 +41,7 @@ MonoStats mono_stats;
 gboolean mono_print_vtable = FALSE;
 
 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
-static void mono_class_create_generic_2 (MonoGenericClass *gclass);
+static void mono_class_create_generic (MonoInflatedGenericClass *gclass);
 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
 
 void (*mono_debugger_start_class_init_func) (MonoClass *klass) = NULL;
@@ -74,11 +74,27 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
        case MONO_RESOLTION_SCOPE_TYPEREF: {
                MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
                GList *tmp;
-               mono_class_init (enclosing);
-               for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
-                       res = tmp->data;
-                       if (strcmp (res->name, name) == 0)
-                               return res;
+
+               if (enclosing->inited) {
+                       /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
+                       for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
+                               res = tmp->data;
+                               if (strcmp (res->name, name) == 0)
+                                       return res;
+                       }
+               } else {
+                       /* Don't call mono_class_init as we might've been called by it recursively */
+                       int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
+                       while (i) {
+                               guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
+                               guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
+                               const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
+
+                               if (strcmp (nname, name) == 0)
+                                       return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested);
+
+                               i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
+                       }
                }
                g_warning ("TypeRef ResolutionScope not yet handled (%d)", idx);
                return NULL;
@@ -98,57 +114,127 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
        return mono_class_from_name (image, nspace, name);
 }
 
-static MonoType*
+static inline MonoType*
 dup_type (MonoType* t, const MonoType *original)
 {
        MonoType *r = g_new0 (MonoType, 1);
        *r = *t;
        r->attrs = original->attrs;
        r->byref = original->byref;
+       if (t->type == MONO_TYPE_PTR)
+               t->data.type = dup_type (t->data.type, original->data.type);
+       else if (t->type == MONO_TYPE_ARRAY)
+               t->data.array = mono_dup_array_type (t->data.array);
+       else if (t->type == MONO_TYPE_FNPTR)
+               t->data.method = mono_metadata_signature_deep_dup (t->data.method);
        mono_stats.generics_metadata_size += sizeof (MonoType);
        return r;
 }
 
+/* Copy everything mono_metadata_free_array free. */
+MonoArrayType *
+mono_dup_array_type (MonoArrayType *a)
+{
+       a = g_memdup (a, sizeof (MonoArrayType));
+       if (a->sizes)
+               a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
+       if (a->lobounds)
+               a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
+       return a;
+}
+
+/* Copy everything mono_metadata_free_method_signature free. */
+MonoMethodSignature*
+mono_metadata_signature_deep_dup (MonoMethodSignature *sig)
+{
+       int i;
+       
+       sig = mono_metadata_signature_dup (sig);
+       
+       sig->ret = dup_type (sig->ret, sig->ret);
+       for (i = 0; i < sig->param_count; ++i)
+               sig->params [i] = dup_type (sig->params [i], sig->params [i]);
+       
+       return sig;
+}
+
+static void
+_mono_type_get_assembly_name (MonoClass *klass, GString *str)
+{
+       MonoAssembly *ta = klass->image->assembly;
+
+       g_string_append_printf (
+               str, ", %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
+               ta->aname.name,
+               ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
+               ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
+               ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
+}
+
 static void
 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
-                           gboolean include_ns, gboolean include_arity)
+                           MonoTypeNameFormat format)
 {
        MonoClass *klass;
        
        switch (type->type) {
        case MONO_TYPE_ARRAY: {
                int i, rank = type->data.array->rank;
+               MonoTypeNameFormat nested_format;
+
+               nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
+                       MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
 
                mono_type_get_name_recurse (
-                       &type->data.array->eklass->byval_arg, str,
-                       FALSE, include_ns, include_arity);
+                       &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
                g_string_append_c (str, '[');
                for (i = 1; i < rank; i++)
                        g_string_append_c (str, ',');
                g_string_append_c (str, ']');
+               if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
+                       _mono_type_get_assembly_name (type->data.array->eklass, str);
                break;
        }
-       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_SZARRAY: {
+               MonoTypeNameFormat nested_format;
+
+               nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
+                       MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
+
                mono_type_get_name_recurse (
-                       &type->data.klass->byval_arg, str, FALSE, include_ns, include_arity);
+                       &type->data.klass->byval_arg, str, FALSE, nested_format);
                g_string_append (str, "[]");
+               if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
+                       _mono_type_get_assembly_name (type->data.klass, str);
                break;
-       case MONO_TYPE_PTR:
-               mono_type_get_name_recurse (type->data.type, str, FALSE, include_ns, include_arity);
-               g_string_append_c (str, '*');
+       }
+       case MONO_TYPE_PTR: {
+               MonoTypeNameFormat nested_format;
+
+               nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
+                       MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
+
+               mono_type_get_name_recurse (
+                       type->data.type, str, FALSE, nested_format);
+               g_string_append (str, "*");
+               if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
+                       _mono_type_get_assembly_name (type->data.klass, str);
                break;
+       }
        default:
                klass = mono_class_from_mono_type (type);
                if (klass->nested_in) {
                        mono_type_get_name_recurse (
-                               &klass->nested_in->byval_arg, str, TRUE, include_ns, include_arity);
-                       g_string_append_c (str, '+');
-               }
-               if (include_ns && *klass->name_space) {
+                               &klass->nested_in->byval_arg, str, TRUE, format);
+                       if (format == MONO_TYPE_NAME_FORMAT_IL)
+                               g_string_append_c (str, '.');
+                       else
+                               g_string_append_c (str, '+');
+               } else if (*klass->name_space) {
                        g_string_append (str, klass->name_space);
                        g_string_append_c (str, '.');
                }
-               if (!include_arity) {
+               if (format == MONO_TYPE_NAME_FORMAT_IL) {
                        char *s = strchr (klass->name, '`');
                        int len = s ? s - klass->name : strlen (klass->name);
 
@@ -159,27 +245,56 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
                        break;
                if (klass->generic_class) {
                        MonoGenericClass *gclass = klass->generic_class;
+                       MonoTypeNameFormat nested_format;
                        int i;
 
-                       g_string_append_c (str, '[');
+                       nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
+                               MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
+
+                       if (format == MONO_TYPE_NAME_FORMAT_IL)
+                               g_string_append_c (str, '<');
+                       else
+                               g_string_append_c (str, '[');
                        for (i = 0; i < gclass->inst->type_argc; i++) {
+                               MonoType *t = gclass->inst->type_argv [i];
+
                                if (i)
                                        g_string_append_c (str, ',');
+                               if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
+                                   (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
+                                       g_string_append_c (str, '[');
                                mono_type_get_name_recurse (
-                                       gclass->inst->type_argv [i], str, FALSE, include_ns, include_arity);
+                                       gclass->inst->type_argv [i], str, FALSE, nested_format);
+                               if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
+                                   (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
+                                       g_string_append_c (str, ']');
                        }
-                       g_string_append_c (str, ']');
-               } else if (klass->generic_container) {
+                       if (format == MONO_TYPE_NAME_FORMAT_IL) 
+                               g_string_append_c (str, '>');
+                       else
+                               g_string_append_c (str, ']');
+               } else if (klass->generic_container &&
+                          (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
+                          (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
                        int i;
 
-                       g_string_append_c (str, '[');
+                       if (format == MONO_TYPE_NAME_FORMAT_IL) 
+                               g_string_append_c (str, '<');
+                       else
+                               g_string_append_c (str, '[');
                        for (i = 0; i < klass->generic_container->type_argc; i++) {
                                if (i)
                                        g_string_append_c (str, ',');
                                g_string_append (str, klass->generic_container->type_params [i].name);
                        }
-                       g_string_append_c (str, ']');
+                       if (format == MONO_TYPE_NAME_FORMAT_IL) 
+                               g_string_append_c (str, '>');
+                       else
+                               g_string_append_c (str, ']');
                }
+               if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
+                   (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
+                       _mono_type_get_assembly_name (klass, str);
                break;
        }
 }
@@ -191,12 +306,19 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
  * Returns: the string representation for type as required by System.Reflection.
  * The inverse of mono_reflection_parse_type ().
  */
-static char*
-_mono_type_get_name (MonoType *type, gboolean is_recursed, gboolean include_ns,
-                    gboolean include_arity)
+char*
+mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
 {
-       GString* result = g_string_new ("");
-       mono_type_get_name_recurse (type, result, is_recursed, include_ns, include_arity);
+       GString* result;
+
+       if (format == MONO_TYPE_NAME_FORMAT_FULL_NAME &&
+           ((type->type == MONO_TYPE_VAR) || (type->type == MONO_TYPE_MVAR) ||
+            ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->inst->is_open)))
+               return NULL;
+
+       result = g_string_new ("");
+
+       mono_type_get_name_recurse (type, result, FALSE, format);
 
        if (type->byref)
                g_string_append_c (result, '&');
@@ -207,13 +329,7 @@ _mono_type_get_name (MonoType *type, gboolean is_recursed, gboolean include_ns,
 char*
 mono_type_get_name (MonoType *type)
 {
-       return _mono_type_get_name (type, TRUE, TRUE, TRUE);
-}
-
-char*
-mono_type_get_full_name (MonoType *type)
-{
-       return _mono_type_get_name (type, FALSE, TRUE, TRUE);
+       return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
 }
 
 MonoType*
@@ -265,20 +381,26 @@ mono_class_is_open_constructed_type (MonoType *t)
 static MonoGenericClass *
 inflate_generic_class (MonoGenericClass *ogclass, MonoGenericContext *context)
 {
+       MonoInflatedGenericClass *igclass;
        MonoGenericClass *ngclass, *cached;
 
        if (ogclass->is_dynamic) {
                MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
-               ngclass = &dgclass->generic_class;
+               igclass = &dgclass->generic_class;
+               ngclass = &igclass->generic_class;
+               ngclass->is_inflated = 1;
                ngclass->is_dynamic = 1;
-       } else
-               ngclass = g_new0 (MonoGenericClass, 1);
+       } else {
+               igclass = g_new0 (MonoInflatedGenericClass, 1);
+               ngclass = &igclass->generic_class;
+               ngclass->is_inflated = 1;
+       }
 
        *ngclass = *ogclass;
 
        ngclass->inst = mono_metadata_inflate_generic_inst (ogclass->inst, context);
 
-       ngclass->klass = NULL;
+       igclass->klass = NULL;
 
        ngclass->context = g_new0 (MonoGenericContext, 1);
        ngclass->context->container = context->container;
@@ -288,12 +410,11 @@ inflate_generic_class (MonoGenericClass *ogclass, MonoGenericContext *context)
        cached = mono_metadata_lookup_generic_class (ngclass);
        mono_loader_unlock ();
        if (cached) {
+               g_free (ngclass->context);
                g_free (ngclass);
                return cached;
        }
 
-       mono_class_create_generic (ngclass);
-
        return ngclass;
 }
 
@@ -324,6 +445,16 @@ inflate_generic_type (MonoType *type, MonoGenericContext *context)
                nt->data.klass = mono_class_from_mono_type (inflated);
                return nt;
        }
+       case MONO_TYPE_ARRAY: {
+               MonoClass *eclass = type->data.array->eklass;
+               MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
+               if (!inflated)
+                       return NULL;
+               nt = dup_type (type, type);
+               nt->data.array = g_memdup (nt->data.array, sizeof (MonoArrayType));
+               nt->data.array->eklass = mono_class_from_mono_type (inflated);
+               return nt;
+       }
        case MONO_TYPE_GENERICINST: {
                MonoGenericClass *ngclass = inflate_generic_class (type->data.generic_class, context);
                MonoType *nt = dup_type (type, type);
@@ -352,6 +483,14 @@ inflate_generic_type (MonoType *type, MonoGenericContext *context)
        return NULL;
 }
 
+MonoInflatedGenericClass*
+mono_get_inflated_generic_class (MonoGenericClass *gclass)
+{
+       g_assert (gclass->is_inflated);
+       mono_class_create_generic ((MonoInflatedGenericClass *) gclass);
+       return (MonoInflatedGenericClass *) gclass;
+}
+
 MonoType*
 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
 {
@@ -385,6 +524,7 @@ mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig
        res->hasthis = sig->hasthis;
        res->explicit_this = sig->explicit_this;
        res->call_convention = sig->call_convention;
+       res->pinvoke = sig->pinvoke;
        res->generic_param_count = sig->generic_param_count;
        res->sentinelpos = sig->sentinelpos;
        res->has_type_parameters = is_open;
@@ -422,6 +562,7 @@ inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflat
 
        if (context->gmethod) {
                res->gmethod = g_new0 (MonoGenericMethod, 1);
+               res->gmethod->generic_class = res->gclass;
 
                res->gmethod->container = context->gmethod->container;
                res->gmethod->inst = mono_metadata_inflate_generic_inst (context->gmethod->inst, inflate_with);
@@ -432,16 +573,11 @@ inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflat
 }
 
 MonoMethod*
-mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context,
-                                  MonoClass *klass)
+mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
 {
        MonoMethodInflated *result;
 
-       if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
-           (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
-               return method;
-
-       if (method->is_inflated || mono_method_signature (method)->is_inflated) {
+       if (method->is_inflated || mono_method_signature_full (method, context)->is_inflated) {
                MonoMethodInflated *imethod = (MonoMethodInflated *) method;
 
                context = inflate_generic_context (imethod->context, context);
@@ -499,17 +635,14 @@ mono_get_inflated_method (MonoMethod *method)
 }
 
 /** 
- * class_compute_field_layout:
+ * mono_class_setup_fields:
  * @m: pointer to the metadata.
  * @class: The class to initialize
  *
  * Initializes the class->fields.
- *
- * Currently we only support AUTO_LAYOUT, and do not even try to do
- * a good job at it.  This is temporary to get the code for Paolo.
  */
 static void
-class_compute_field_layout (MonoClass *class)
+mono_class_setup_fields (MonoClass *class)
 {
        MonoImage *m = class->image; 
        const int top = class->field.count;
@@ -524,9 +657,12 @@ class_compute_field_layout (MonoClass *class)
        if (class->size_inited)
                return;
 
+       class->instance_size = 0;
+       class->class_size = 0;
+
        if (class->parent) {
                if (!class->parent->size_inited)
-                       class_compute_field_layout (class->parent);
+                       mono_class_setup_fields (class->parent);
                class->instance_size += class->parent->instance_size;
                class->min_align = class->parent->min_align;
                /* we use |= since it may have been set already */
@@ -558,6 +694,9 @@ class_compute_field_layout (MonoClass *class)
        if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
                blittable = FALSE;
 
+       /* Prevent infinite loops if the class references itself */
+       class->size_inited = 1;
+
        class->fields = g_new0 (MonoClassField, top);
 
        /*
@@ -580,8 +719,14 @@ class_compute_field_layout (MonoClass *class)
                if (class->generic_container)
                        container = class->generic_container;
                else if (class->generic_class) {
-                       container = class->generic_class->container_class->generic_container;
+                       MonoInflatedField *ifield = g_new0 (MonoInflatedField, 1);
+                       MonoClass *gklass = class->generic_class->container_class;
+
+                       container = gklass->generic_container;
                        g_assert (container);
+
+                       ifield->generic_type = gklass->fields [i].type;
+                       field->generic_info = ifield;
                }
                field->type = mono_metadata_parse_type_full (
                        m, (MonoGenericContext *) container, MONO_PARSE_FIELD,
@@ -642,16 +787,15 @@ class_compute_field_layout (MonoClass *class)
                class->instance_size = MAX (real_size, class->instance_size);
        }
 
-       if (class->generic_container ||
-           (class->generic_class && class->generic_class->inst->is_open))
-               return;
-
        mono_class_layout_fields (class);
 }
 
 /* useful until we keep track of gc-references in corlib etc. */
 #define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U || (t)->type == MONO_TYPE_I || (t)->type == MONO_TYPE_PTR)
 
+/*
+ * LOCKING: this is supposed to be called with the loader lock held.
+ */
 void
 mono_class_layout_fields (MonoClass *class)
 {
@@ -662,6 +806,10 @@ mono_class_layout_fields (MonoClass *class)
        gboolean gc_aware_layout = FALSE;
        MonoClassField *field;
 
+       if (class->generic_container ||
+           (class->generic_class && class->generic_class->inst->is_open))
+               return;
+
        /*
         * Enable GC aware auto layout: in this mode, reference
         * fields are grouped together inside objects, increasing collector 
@@ -678,6 +826,20 @@ mono_class_layout_fields (MonoClass *class)
                        gc_aware_layout = TRUE;
        }
 
+       for (i = 0; i < top; i++) {
+               MonoType *ftype;
+
+               field = &class->fields [i];
+
+               ftype = mono_type_get_underlying_type (field->type);
+               if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_from_mono_type (ftype)->has_references))) {
+                       if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+                               class->has_static_refs = TRUE;
+                       else
+                               class->has_references = TRUE;
+               }
+       }
+
        /*
         * Compute field layout and total size (not considering static fields)
         */
@@ -702,6 +864,7 @@ mono_class_layout_fields (MonoClass *class)
                for (pass = 0; pass < passes; ++pass) {
                        for (i = 0; i < top; i++){
                                int size, align;
+
                                field = &class->fields [i];
 
                                if (mono_field_is_deleted (field))
@@ -741,10 +904,6 @@ mono_class_layout_fields (MonoClass *class)
                                field->offset += align - 1;
                                field->offset &= ~(align - 1);
                                real_size = field->offset + size;
-                               if (MONO_TYPE_IS_REFERENCE (field->type) || IS_GC_REFERENCE (field->type))
-                                       class->has_references = TRUE;
-                               else if (field->type->type == MONO_TYPE_VALUETYPE && field->type->data.klass->has_references)
-                                       class->has_references = TRUE;
                        }
 
                        class->instance_size = MAX (real_size, class->instance_size);
@@ -759,6 +918,7 @@ mono_class_layout_fields (MonoClass *class)
                real_size = 0;
                for (i = 0; i < top; i++) {
                        int size, align;
+
                        field = &class->fields [i];
 
                        /*
@@ -771,10 +931,6 @@ mono_class_layout_fields (MonoClass *class)
                        if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
                                continue;
 
-                       if (MONO_TYPE_IS_REFERENCE (field->type) || IS_GC_REFERENCE (field->type))
-                               class->has_references = TRUE;
-                       else if (field->type->type == MONO_TYPE_VALUETYPE && field->type->data.klass->has_references)
-                               class->has_references = TRUE;
                        size = mono_type_size (field->type, &align);
                        
                        /*
@@ -801,6 +957,7 @@ mono_class_layout_fields (MonoClass *class)
         */
        for (i = 0; i < top; i++){
                int size, align;
+
                field = &class->fields [i];
                        
                if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
@@ -808,10 +965,6 @@ mono_class_layout_fields (MonoClass *class)
                if (mono_field_is_deleted (field))
                        continue;
 
-               if (MONO_TYPE_IS_REFERENCE (field->type) || IS_GC_REFERENCE (field->type))
-                       class->has_static_refs = TRUE;
-               else if (field->type->type == MONO_TYPE_VALUETYPE && field->type->data.klass->has_references)
-                       class->has_static_refs = TRUE;
                size = mono_type_size (field->type, &align);
                field->offset = class->class_size;
                field->offset += align - 1;
@@ -1035,11 +1188,79 @@ mono_class_get_implemented_interfaces (MonoClass *klass)
        return res;
 }
 
+typedef struct _IOffsetInfo IOffsetInfo;
+struct _IOffsetInfo {
+       IOffsetInfo *next;
+       int size;
+       int next_free;
+       int data [MONO_ZERO_LEN_ARRAY];
+};
+
+static IOffsetInfo *cached_offset_info = NULL;
+static int next_offset_info_size = 128;
+
+static int*
+cache_interface_offsets (int max_iid, int *data)
+{
+       IOffsetInfo *cached_info;
+       int *cached;
+       int new_size;
+       for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
+               cached = cached_info->data;
+               while (cached < cached_info->data + cached_info->size && *cached) {
+                       if (*cached == max_iid) {
+                               int i, matched = TRUE;
+                               cached++;
+                               for (i = 0; i < max_iid; ++i) {
+                                       if (cached [i] != data [i]) {
+                                               matched = FALSE;
+                                               break;
+                                       }
+                               }
+                               if (matched)
+                                       return cached;
+                               cached += max_iid;
+                       } else {
+                               cached += *cached + 1;
+                       }
+               }
+       }
+       /* find a free slot */
+       for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
+               if (cached_info->size - cached_info->next_free >= max_iid + 1) {
+                       cached = &cached_info->data [cached_info->next_free];
+                       *cached++ = max_iid;
+                       memcpy (cached, data, max_iid * sizeof (int));
+                       cached_info->next_free += max_iid + 1;
+                       return cached;
+               }
+       }
+       /* allocate a new chunk */
+       if (max_iid + 1 < next_offset_info_size) {
+               new_size = next_offset_info_size;
+               if (next_offset_info_size < 4096)
+                       next_offset_info_size += next_offset_info_size >> 2;
+       } else {
+               new_size = max_iid + 1;
+       }
+       cached_info = g_malloc0 (sizeof (IOffsetInfo) + sizeof (int) * new_size);
+       cached_info->size = new_size;
+       /*g_print ("allocated %d offset entries at %p (total: %d)\n", new_size, cached_info->data, offset_info_total_size);*/
+       cached = &cached_info->data [0];
+       *cached++ = max_iid;
+       memcpy (cached, data, max_iid * sizeof (int));
+       cached_info->next_free += max_iid + 1;
+       cached_info->next = cached_offset_info;
+       cached_offset_info = cached_info;
+       return cached;
+}
+
 static int
 setup_interface_offsets (MonoClass *class, int cur_slot)
 {
        MonoClass *k, *ic;
        int i, max_iid;
+       int *cached_data;
        GPtrArray *ifaces;
 
        /* compute maximum number of slots and maximum interface id */
@@ -1107,6 +1328,10 @@ setup_interface_offsets (MonoClass *class, int cur_slot)
        if (MONO_CLASS_IS_INTERFACE (class))
                class->interface_offsets [class->interface_id] = cur_slot;
 
+       cached_data = cache_interface_offsets (max_iid + 1, class->interface_offsets);
+       g_free (class->interface_offsets);
+       class->interface_offsets = cached_data;
+
        return cur_slot;
 }
 
@@ -1114,6 +1339,7 @@ void
 mono_class_setup_vtable (MonoClass *class)
 {
        MonoMethod **overrides;
+       MonoGenericContext *context;
        int onum = 0;
 
        if (class->vtable)
@@ -1131,13 +1357,52 @@ mono_class_setup_vtable (MonoClass *class)
                return;
        }
 
-       overrides = mono_class_get_overrides (class->image, class->type_token, &onum);  
+       if (class->generic_class)
+               context = class->generic_class->context;
+       else
+               context = (MonoGenericContext *) class->generic_container;              
+
+       overrides = mono_class_get_overrides_full (
+               class->image, class->type_token, &onum, context);
        mono_class_setup_vtable_general (class, overrides, onum);
        g_free (overrides);
 
        mono_loader_unlock ();
 }
 
+static void
+setup_generic_vtable (MonoClass *class, MonoMethod **overrides, int onum)
+{
+       MonoClass *gklass;
+       int i;
+
+       gklass = class->generic_class->container_class;
+
+       mono_class_init (gklass);
+       class->vtable_size = gklass->vtable_size;
+
+       class->vtable = g_new0 (MonoMethod*, class->vtable_size);
+       memcpy (class->vtable, gklass->vtable,  sizeof (MonoMethod*) * class->vtable_size);
+
+       for (i = 0; i < class->vtable_size; i++) {
+               MonoMethod *m = class->vtable [i];
+
+               if (!m)
+                       continue;
+
+               m = mono_class_inflate_generic_method (m, class->generic_class->context);
+               class->vtable [i] = m;
+       }
+
+       class->max_interface_id = gklass->max_interface_id;
+       class->interface_offsets = g_new0 (gint, gklass->max_interface_id + 1);
+       memcpy (class->interface_offsets, gklass->interface_offsets,
+               sizeof (gint) * (gklass->max_interface_id + 1));
+}
+
+/*
+ * LOCKING: this is supposed to be called with the loader lock held.
+ */
 void
 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum)
 {
@@ -1151,6 +1416,11 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
        if (class->vtable)
                return;
 
+       if (class->generic_class) {
+               setup_generic_vtable (class, overrides, onum);
+               return;
+       }
+
        ifaces = mono_class_get_implemented_interfaces (class);
        if (ifaces) {
                for (i = 0; i < ifaces->len; i++) {
@@ -1199,6 +1469,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
 
        for (k = class; k ; k = k->parent) {
                int nifaces = 0;
+
                ifaces = mono_class_get_implemented_interfaces (k);
                if (ifaces)
                        nifaces = ifaces->len;
@@ -1290,8 +1561,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                        continue;
 
                                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);
+                                       the_cname = mono_type_get_name_full (&ic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
                                        cname = the_cname;
                                } else {
                                        the_cname = NULL;
@@ -1310,7 +1580,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
 
                                                if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
                                                        continue;
-                                       
+
                                                if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
                                                    mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
 
@@ -1546,6 +1816,7 @@ mono_class_init (MonoClass *class)
        static int finalize_slot = -1;
        static int ghc_slot = -1;
        MonoCachedClassInfo cached_info;
+       gboolean has_cached_info;
 
        g_assert (class);
 
@@ -1564,6 +1835,7 @@ mono_class_init (MonoClass *class)
        }
 
        if (class->init_pending) {
+               mono_loader_unlock ();
                /* this indicates a cyclic dependency */
                g_error ("pending init %s.%s\n", class->name_space, class->name);
        }
@@ -1581,16 +1853,17 @@ mono_class_init (MonoClass *class)
        mono_stats.initialized_class_count++;
 
        if (class->generic_class && !class->generic_class->is_dynamic) {
-               MonoGenericClass *gclass = class->generic_class;
-               MonoClass *gklass = gclass->container_class;
+               MonoInflatedGenericClass *gclass;
+               MonoClass *gklass;
+
+               gclass = mono_get_inflated_generic_class (class->generic_class);
+               gklass = gclass->generic_class.container_class;
 
                mono_stats.generic_class_count++;
 
                class->method = gklass->method;
                class->field = gklass->field;
 
-               mono_class_create_generic_2 (gclass);
-
                mono_class_init (gklass);
                mono_class_setup_methods (gklass);
                mono_class_setup_properties (gklass);
@@ -1603,25 +1876,11 @@ mono_class_init (MonoClass *class)
 
                for (i = 0; i < class->method.count; i++) {
                        MonoMethod *inflated = mono_class_inflate_generic_method (
-                               gklass->methods [i], gclass->context, gclass->klass);
+                               gklass->methods [i], gclass->generic_class.context);
 
                        class->methods [i] = mono_get_inflated_method (inflated);
                }
 
-               g_assert (class->field.count == gklass->field.count);
-               class->fields = g_new0 (MonoClassField, class->field.count);
-
-               for (i = 0; i < class->field.count; i++) {
-                       MonoInflatedField *ifield = g_new0 (MonoInflatedField, 1);
-                       ifield->generic_type = gklass->fields [i].type;
-
-                       class->fields [i] = gklass->fields [i];
-                       class->fields [i].generic_info = ifield;
-                       class->fields [i].parent = class;
-                       class->fields [i].type = mono_class_inflate_generic_type (
-                               class->fields [i].type, gclass->context);
-               }
-
                class->property = gklass->property;
                class->properties = g_new0 (MonoProperty, class->property.count);
 
@@ -1632,10 +1891,10 @@ mono_class_init (MonoClass *class)
 
                        if (prop->get)
                                prop->get = mono_class_inflate_generic_method (
-                                       prop->get, gclass->context, gclass->klass);
+                                       prop->get, gclass->generic_class.context);
                        if (prop->set)
                                prop->set = mono_class_inflate_generic_method (
-                                       prop->set, gclass->context, gclass->klass);
+                                       prop->set, gclass->generic_class.context);
 
                        prop->parent = class;
                }
@@ -1646,11 +1905,36 @@ mono_class_init (MonoClass *class)
        if (class->parent && !class->parent->inited)
                mono_class_init (class->parent);
 
+       has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
+
+       if (!class->generic_class && (!has_cached_info || (has_cached_info && cached_info.has_nested_classes))) {
+               i = mono_metadata_nesting_typedef (class->image, class->type_token, 1);
+               while (i) {
+                       MonoClass* nclass;
+                       guint32 cols [MONO_NESTED_CLASS_SIZE];
+                       mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
+                       nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
+                       class->nested_classes = g_list_prepend (class->nested_classes, nclass);
+
+                       i = mono_metadata_nesting_typedef (class->image, class->type_token, i + 1);
+               }
+       }
+
        /*
         * Computes the size used by the fields, and their locations
         */
-       if (!class->size_inited)
-               class_compute_field_layout (class);
+       if (has_cached_info) {
+               class->instance_size = cached_info.instance_size;
+               class->class_size = cached_info.class_size;
+               class->packing_size = cached_info.packing_size;
+               class->min_align = cached_info.min_align;
+               class->blittable = cached_info.blittable;
+               class->has_references = cached_info.has_references;
+               class->has_static_refs = cached_info.has_static_refs;
+       }
+       else
+               if (!class->size_inited)
+                       mono_class_setup_fields (class);
 
        /* initialize method pointers */
        if (class->rank) {
@@ -1690,37 +1974,8 @@ mono_class_init (MonoClass *class)
                }
        }
 
-       if (!class->generic_class) {
-               i = mono_metadata_nesting_typedef (class->image, class->type_token, 1);
-               while (i) {
-                       MonoClass* nclass;
-                       guint32 cols [MONO_NESTED_CLASS_SIZE];
-                       mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
-                       nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
-                       class->nested_classes = g_list_prepend (class->nested_classes, nclass);
-
-                       i = mono_metadata_nesting_typedef (class->image, class->type_token, i + 1);
-               }
-       }
-
        mono_class_setup_supertypes (class);
 
-       if (MONO_CLASS_IS_INTERFACE (class)) {
-               class->init_pending = 0;
-               class->inited = 1;
-               /* 
-                * class->interface_offsets is needed for the castclass/isinst code, so
-                * we have to setup them for interfaces, too.
-                */
-               setup_interface_offsets (class, 0);
-               mono_loader_unlock ();
-
-               if (mono_debugger_class_init_func)
-                       mono_debugger_class_init_func (class);
-
-               return;
-       }
-
        if (!default_ghc) {
                if (class == mono_defaults.object_class) { 
                        mono_class_setup_vtable (class);                       
@@ -1761,7 +2016,7 @@ mono_class_init (MonoClass *class)
         * If possible, avoid the creation of the generic vtable by requesting
         * cached info from the runtime.
         */
-       if (mono_class_get_cached_class_info (class, &cached_info)) {
+       if (has_cached_info) {
                guint32 cur_slot = 0;
 
                class->vtable_size = cached_info.vtable_size;
@@ -1781,7 +2036,10 @@ mono_class_init (MonoClass *class)
        
                class->ghcimpl = 1;
                if (class->parent) { 
-                       if (class->vtable [ghc_slot] == default_ghc) {
+                       MonoMethod *cmethod = class->vtable [ghc_slot];
+                       if (cmethod->is_inflated)
+                               cmethod = ((MonoMethodInflated*)cmethod)->declaring;
+                       if (cmethod == default_ghc) {
                                class->ghcimpl = 0;
                        }
                }
@@ -1789,8 +2047,12 @@ mono_class_init (MonoClass *class)
                /* Object::Finalize should have empty implemenatation */
                class->has_finalize = 0;
                if (class->parent) { 
-                       if (class->vtable [finalize_slot] != default_finalize)
+                       MonoMethod *cmethod = class->vtable [finalize_slot];
+                       if (cmethod->is_inflated)
+                               cmethod = ((MonoMethodInflated*)cmethod)->declaring;
+                       if (cmethod != default_finalize) {
                                class->has_finalize = 1;
+                       }
                }
 
                for (i = 0; i < class->method.count; ++i) {
@@ -1808,10 +2070,21 @@ mono_class_init (MonoClass *class)
        
        mono_loader_unlock ();
 
+       if (MONO_CLASS_IS_INTERFACE (class)) {
+               /* 
+                * class->interface_offsets is needed for the castclass/isinst code, so
+                * we have to setup them for interfaces, too.
+                */
+               setup_interface_offsets (class, 0);
+       }
+
        if (mono_debugger_class_init_func)
                mono_debugger_class_init_func (class);
 }
 
+/*
+ * LOCKING: this assumes the loader lock is held
+ */
 void
 mono_class_setup_mono_type (MonoClass *class)
 {
@@ -1931,6 +2204,9 @@ mono_class_setup_mono_type (MonoClass *class)
        }
 }
 
+/*
+ * LOCKING: this assumes the loader lock is held
+ */
 void
 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
 {
@@ -1950,9 +2226,6 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
                return;
        }
 
-       if (parent && parent->generic_class)
-               mono_class_create_generic_2 (parent->generic_class);
-
        if (!MONO_CLASS_IS_INTERFACE (class)) {
                class->parent = parent;
 
@@ -1997,26 +2270,30 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
 
 }
 
+/*
+ * LOCKING: this assumes the loader lock is held
+ */
 void
 mono_class_setup_supertypes (MonoClass *class)
 {
-       MonoClass *k;
-       int ms, i;
+       int ms;
 
        if (class->supertypes)
                return;
 
-       class->idepth = 0;
-       for (k = class; k ; k = k->parent) {
-               class->idepth++;
-       }
+       if (class->parent && !class->parent->supertypes)
+               mono_class_setup_supertypes (class->parent);
+       if (class->parent)
+               class->idepth = class->parent->idepth + 1;
+       else
+               class->idepth = 1;
 
        ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
        class->supertypes = g_new0 (MonoClass *, ms);
 
        if (class->parent) {
-               for (i = class->idepth, k = class; k ; k = k->parent)
-                       class->supertypes [--i] = k;
+               class->supertypes [class->idepth - 1] = class;
+               memcpy (class->supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
        } else {
                class->supertypes [0] = class;
        }
@@ -2071,14 +2348,20 @@ get_shared_inst (MonoGenericContainer *container)
 MonoGenericClass *
 mono_get_shared_generic_class (MonoGenericContainer *container, gboolean is_dynamic)
 {
+       MonoInflatedGenericClass *igclass;
        MonoGenericClass *gclass;
 
        if (is_dynamic) {
                MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
-               gclass = &dgclass->generic_class;
+               igclass = &dgclass->generic_class;
+               gclass = &igclass->generic_class;
+               gclass->is_inflated = 1;
                gclass->is_dynamic = 1;
-       } else
-               gclass = g_new0 (MonoGenericClass, 1);
+       } else {
+               igclass = g_new0 (MonoInflatedGenericClass, 1);
+               gclass = &igclass->generic_class;
+               gclass->is_inflated = 1;
+       }
 
        gclass->context = &container->context;
        gclass->container_class = container->klass;
@@ -2093,7 +2376,7 @@ mono_get_shared_generic_class (MonoGenericContainer *container, gboolean is_dyna
                }
        }
 
-       gclass->klass = container->klass;
+       igclass->klass = container->klass;
 
        return gclass;
 }
@@ -2205,7 +2488,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        }
 
        if (class->enumtype)
-               class_compute_field_layout (class);
+               mono_class_setup_fields (class);
 
        if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
                class->nested_in = mono_class_create_from_typedef (image, type_token);
@@ -2218,16 +2501,21 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        return class;
 }
 
-void
-mono_class_create_generic (MonoGenericClass *gclass)
+static void
+mono_class_create_generic (MonoInflatedGenericClass *gclass)
 {
        MonoClass *klass, *gklass;
+       int i;
+
+       if (gclass->is_initialized)
+               return;
+       gclass->is_initialized = TRUE;
 
        if (!gclass->klass)
                gclass->klass = g_malloc0 (sizeof (MonoClass));
        klass = gclass->klass;
 
-       gklass = gclass->container_class;
+       gklass = gclass->generic_class.container_class;
 
        klass->nested_in = gklass->nested_in;
 
@@ -2236,15 +2524,15 @@ mono_class_create_generic (MonoGenericClass *gclass)
        klass->image = gklass->image;
        klass->flags = gklass->flags;
 
-       klass->generic_class = gclass;
+       klass->generic_class = &gclass->generic_class;
 
        klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
-       klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
+       klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = &gclass->generic_class;
        klass->this_arg.byref = TRUE;
 
        klass->cast_class = klass->element_class = klass;
 
-       if (gclass->is_dynamic) {
+       if (gclass->generic_class.is_dynamic) {
                klass->instance_size = gklass->instance_size;
                klass->class_size = gklass->class_size;
                klass->size_inited = 1;
@@ -2254,34 +2542,35 @@ mono_class_create_generic (MonoGenericClass *gclass)
 
                mono_class_setup_supertypes (klass);
        }
-}
-
-static void
-mono_class_create_generic_2 (MonoGenericClass *gclass)
-{
-       MonoClass *klass, *gklass;
-       GList *list;
-       int i;
-
-       klass = gclass->klass;
-       gklass = gclass->container_class;
 
        klass->interface_count = gklass->interface_count;
        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, gclass->context);
+               MonoType *inflated = mono_class_inflate_generic_type (
+                       it, gclass->generic_class.context);
                klass->interfaces [i] = mono_class_from_mono_type (inflated);
        }
 
-       for (list = gklass->nested_classes; list; list = list->next)
-               klass->nested_classes = g_list_append (
-                       klass->nested_classes, list->data);
+       i = mono_metadata_nesting_typedef (klass->image, gklass->type_token, 1);
+       while (i) {
+               MonoClass* nclass;
+               guint32 cols [MONO_NESTED_CLASS_SIZE];
+               mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
+               nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
+               klass->nested_classes = g_list_prepend (klass->nested_classes, nclass);
+               
+               i = mono_metadata_nesting_typedef (klass->image, gklass->type_token, i + 1);
+       }
+
+       if (gclass->generic_class.is_dynamic) {
+               MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *) gclass;
 
-       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, gclass->context);
+               if (dgclass->parent)
+                       klass->parent = mono_class_from_mono_type (dgclass->parent);
+       } else if (gklass->parent) {
+               MonoType *inflated = mono_class_inflate_generic_type (
+                       &gklass->parent->byval_arg, gclass->generic_class.context);
 
                klass->parent = mono_class_from_mono_type (inflated);
        }
@@ -2308,7 +2597,10 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb
        if ((count > 0) && !MONO_CLASS_IS_INTERFACE (param->constraints [0])) {
                klass->parent = param->constraints [0];
                pos++;
-       }
+       } else if (param->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
+               klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
+       else
+               klass->parent = mono_defaults.object_class;
 
        if (count - pos > 0) {
                klass->interface_count = count - pos;
@@ -2322,6 +2614,7 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb
        klass->name = param->name;
        klass->name_space = "";
        klass->image = image;
+       klass->inited = TRUE;
        klass->cast_class = klass->element_class = klass;
        klass->enum_basetype = &klass->element_class->byval_arg;
        klass->flags = TYPE_ATTRIBUTE_PUBLIC;
@@ -2330,7 +2623,7 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb
        klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
        klass->this_arg.byref = TRUE;
 
-       mono_class_init (klass);
+       mono_class_setup_supertypes (klass);
 
        return klass;
 }
@@ -2353,6 +2646,7 @@ my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar)
                klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
        klass->name_space = "";
        klass->image = mono_defaults.corlib;
+       klass->inited = TRUE;
        klass->cast_class = klass->element_class = klass;
        klass->enum_basetype = &klass->element_class->byval_arg;
        klass->flags = TYPE_ATTRIBUTE_PUBLIC;
@@ -2361,7 +2655,7 @@ my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar)
        klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
        klass->this_arg.byref = TRUE;
 
-       mono_class_init (klass);
+       mono_class_setup_supertypes (klass);
 
        return klass;
 }
@@ -2503,9 +2797,12 @@ mono_class_from_mono_type (MonoType *type)
        case MONO_TYPE_CLASS:
        case MONO_TYPE_VALUETYPE:
                return type->data.klass;
-       case MONO_TYPE_GENERICINST:
-               g_assert (type->data.generic_class->klass);
-               return type->data.generic_class->klass;
+       case MONO_TYPE_GENERICINST: {
+               MonoInflatedGenericClass *gclass;
+               gclass = mono_get_inflated_generic_class (type->data.generic_class);
+               g_assert (gclass->klass);
+               return gclass->klass;
+       }
        case MONO_TYPE_VAR:
                return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE);
        case MONO_TYPE_MVAR:
@@ -2533,7 +2830,7 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec,
 
        switch (type->type) {
        case MONO_TYPE_ARRAY:
-               class = mono_array_class_get (type->data.array->eklass, type->data.array->rank);
+               class = mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
                break;
        case MONO_TYPE_SZARRAY:
                class = mono_array_class_get (type->data.klass, 1);
@@ -2541,10 +2838,13 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec,
        case MONO_TYPE_PTR:
                class = mono_ptr_class_get (type->data.type);
                break;
-       case MONO_TYPE_GENERICINST:
-               g_assert (type->data.generic_class->klass);
-               class = type->data.generic_class->klass;
+       case MONO_TYPE_GENERICINST: {
+               MonoInflatedGenericClass *gclass;
+               gclass = mono_get_inflated_generic_class (type->data.generic_class);
+               g_assert (gclass->klass);
+               class = gclass->klass;
                break;
+       }
        default:
                /* it seems any type can be stored in TypeSpec as well */
                class = mono_class_from_mono_type (type);
@@ -2600,9 +2900,21 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
        }
 
        /* for the building corlib use System.Array from it */
-       if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "mscorlib") == 0) {
+       if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
                parent = mono_class_from_name (image, "System", "Array");
                corlib_type = TRUE;
+       } else if (mono_defaults.generic_array_class) {
+               MonoType *inflated, **args;
+
+               args = g_new0 (MonoType *, 1);
+               args [0] = &eclass->byval_arg;
+
+               inflated = mono_class_bind_generic_parameters (
+                       &mono_defaults.generic_array_class->byval_arg, 1, args);
+               parent = mono_class_from_mono_type (inflated);
+
+               if (!parent->inited)
+                       mono_class_init (parent);
        } else {
                parent = mono_defaults.array_class;
                if (!parent->inited)
@@ -2630,8 +2942,10 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
        class->instance_size = mono_class_instance_size (class->parent);
        class->class_size = 0;
        mono_class_setup_supertypes (class);
+       if (eclass->generic_class)
+               mono_class_init (eclass);
        if (!eclass->size_inited)
-               class_compute_field_layout (eclass);
+               mono_class_setup_fields (eclass);
        class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
 
        class->rank = rank;
@@ -2694,8 +3008,6 @@ mono_class_instance_size (MonoClass *klass)
        if (!klass->size_inited)
                mono_class_init (klass);
 
-       g_assert (!klass->generic_container &&
-                 (!klass->generic_class || !klass->generic_class->inst->is_open));
        return klass->instance_size;
 }
 
@@ -2764,6 +3076,8 @@ mono_class_data_size (MonoClass *klass)
 static MonoClassField *
 mono_class_get_field_idx (MonoClass *class, int idx)
 {
+       mono_class_setup_fields (class);
+
        if (class->field.count){
                if ((idx >= class->field.first) && (idx < class->field.last)){
                        return &class->fields [idx - class->field.first];
@@ -2801,6 +3115,7 @@ mono_class_get_field_from_name (MonoClass *klass, const char *name)
        int i;
 
        while (klass) {
+               mono_class_setup_fields (klass);
                for (i = 0; i < klass->field.count; ++i) {
                        if (strcmp (name, klass->fields [i].name) == 0)
                                return &klass->fields [i];
@@ -2817,6 +3132,7 @@ mono_class_get_field_token (MonoClassField *field)
        int i;
 
        while (klass) {
+               mono_class_setup_fields (klass);
                for (i = 0; i < klass->field.count; ++i) {
                        if (&klass->fields [i] == field)
                                return mono_metadata_make_token (MONO_TABLE_FIELD, klass->field.first + i + 1);
@@ -2904,7 +3220,10 @@ mono_class_name_from_token (MonoImage *image, guint32 type_token, MonoGenericCon
                mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
                name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
                nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
-               return g_strdup_printf ("%s.%s", nspace, name);
+               if (strlen (nspace) == 0)
+                       return g_strdup_printf ("%s", name);
+               else
+                       return g_strdup_printf ("%s.%s", nspace, name);
        }
 
        case MONO_TOKEN_TYPE_REF: {
@@ -2914,7 +3233,10 @@ mono_class_name_from_token (MonoImage *image, guint32 type_token, MonoGenericCon
                mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
                name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
                nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
-               return g_strdup_printf ("%s.%s", nspace, name);
+               if (strlen (nspace) == 0)
+                       return g_strdup_printf ("%s", name);
+               else
+                       return g_strdup_printf ("%s.%s", nspace, name);
        }
                
        case MONO_TOKEN_TYPE_SPEC:
@@ -2959,7 +3281,7 @@ _mono_class_get (MonoImage *image, guint32 type_token, MonoGenericContext *conte
 
        if (!class){
                char *name = mono_class_name_from_token (image, type_token, context);
-               g_warning ("Could not load class from %s (token 0x%08x) in %s", name, type_token, image->name);
+               g_warning ("The class %s could not be loaded, used in %s (token 0x%08x)", name, image->name, type_token);
                g_free (name);
        }
 
@@ -3000,6 +3322,21 @@ mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *c
        return mono_class_from_mono_type (inflated);
 }
 
+typedef struct {
+       gconstpointer key;
+       gpointer value;
+} FindUserData;
+
+static void
+find_nocase (gpointer key, gpointer value, gpointer user_data)
+{
+       char *name = (char*)key;
+       FindUserData *data = (FindUserData*)user_data;
+
+       if (!data->value && (g_strcasecmp (name, (char*)data->key) == 0))
+               data->value = value;
+}
+
 /**
  * mono_class_from_name_case:
  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
@@ -3025,6 +3362,37 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char
        const char *nspace;
        guint32 i, visib;
 
+       if (image->dynamic) {
+               guint32 token = 0;
+               FindUserData user_data;
+
+               mono_loader_lock ();
+
+               user_data.key = name_space;
+               user_data.value = NULL;
+               g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
+
+               if (user_data.value) {
+                       GHashTable *nspace_table = (GHashTable*)user_data.value;
+
+                       user_data.key = name;
+                       user_data.value = NULL;
+
+                       g_hash_table_foreach (nspace_table, find_nocase, &user_data);
+                       
+                       if (user_data.value)
+                               token = GPOINTER_TO_UINT (user_data.value);
+               }
+
+               mono_loader_unlock ();
+               
+               if (token)
+                       return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
+               else
+                       return NULL;
+
+       }
+
        /* add a cache if needed */
        for (i = 1; i <= t->rows; ++i) {
                mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
@@ -3063,7 +3431,7 @@ return_nested_in (MonoClass *class, char *nested) {
 
 
 /**
- * mono_class_from_name_case:
+ * mono_class_from_name:
  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
  * @name_space: the type namespace
  * @name: the type short name.
@@ -3171,14 +3539,15 @@ mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
        if (klassc == mono_defaults.object_class)
                return TRUE;
 
-       if (klass->generic_class) {
-               MonoType *parent = klass->generic_class->parent;
-               if (!parent)
+       if (klass->generic_class && klass->generic_class->is_dynamic) {
+               MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *) klass->generic_class;
+
+               if (!dgclass->parent)
                        return FALSE;
 
-               if (mono_metadata_type_equal (parent, &klassc->byval_arg))
+               if (mono_metadata_type_equal (dgclass->parent, &klassc->byval_arg))
                        return TRUE;
-               klass = mono_class_from_mono_type (parent);
+               klass = mono_class_from_mono_type (dgclass->parent);
                goto again;
        }
        
@@ -3196,8 +3565,21 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
 
        if (klass->generic_class)
                klass = klass->generic_class->container_class;
+       if (oklass->generic_class)
+               oklass = oklass->generic_class->container_class;
 
        if (MONO_CLASS_IS_INTERFACE (klass)) {
+               if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR))
+                       return FALSE;
+
+               /* interface_offsets might not be set for dynamic classes */
+               if (oklass->reflection_info && !oklass->interface_offsets)
+                       /* 
+                        * oklass might be a generic type parameter but they have 
+                        * interface_offsets set.
+                        */
+                       return mono_reflection_call_is_assignable_to (oklass, klass);
+
                if ((klass->interface_id <= oklass->max_interface_id) &&
                    (oklass->interface_offsets [klass->interface_id] != -1))
                        return TRUE;
@@ -3234,7 +3616,19 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
                if (klass == mono_defaults.object_class)
                        return TRUE;
 
-       return mono_class_has_parent (oklass, klass);
+       /*
+        * Custom version of mono_class_has_parent (oklass, klass)
+        */
+       if (oklass->idepth >= klass->idepth) {
+               MonoClass *parent = oklass->supertypes [klass->idepth - 1];
+
+               if (parent->generic_class)
+                       parent = parent->generic_class->container_class;
+
+               return klass == parent;
+       }
+
+       return FALSE;
 }      
 
 /*
@@ -3384,26 +3778,17 @@ mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
              MonoGenericContext *context)
 {
        if (image->dynamic) {
-               gpointer obj = mono_lookup_dynamic_token (image, token);
+               MonoClass *tmp_handle_class;
+               gpointer obj = mono_lookup_dynamic_token_class (image, token, &tmp_handle_class);
 
-               switch (token & 0xff000000) {
-               case MONO_TOKEN_TYPE_DEF:
-               case MONO_TOKEN_TYPE_REF:
-               case MONO_TOKEN_TYPE_SPEC:
-                       if (handle_class)
-                               *handle_class = mono_defaults.typehandle_class;
+               g_assert (tmp_handle_class);
+               if (handle_class)
+                       *handle_class = tmp_handle_class;
+
+               if (tmp_handle_class == mono_defaults.typehandle_class)
                        return &((MonoClass*)obj)->byval_arg;
-               case MONO_TOKEN_METHOD_DEF:
-                       if (handle_class)
-                               *handle_class = mono_defaults.methodhandle_class;
-                       return obj;
-               case MONO_TOKEN_FIELD_DEF:
-                       if (handle_class)
-                               *handle_class = mono_defaults.fieldhandle_class;
+               else
                        return obj;
-               default:
-                       g_assert_not_reached ();
-               }
        }
 
        switch (token & 0xff000000) {
@@ -3484,7 +3869,15 @@ mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
 gpointer
 mono_lookup_dynamic_token (MonoImage *image, guint32 token)
 {
-       return lookup_dynamic (image, token);
+       MonoClass *handle_class;
+
+       return lookup_dynamic (image, token, &handle_class);
+}
+
+gpointer
+mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, MonoClass **handle_class)
+{
+       return lookup_dynamic (image, token, handle_class);
 }
 
 static MonoGetCachedClassInfo get_cached_class_info = NULL;
@@ -3733,6 +4126,7 @@ mono_class_get_fields (MonoClass* klass, gpointer *iter)
        if (!klass->inited)
                mono_class_init (klass);
        if (!*iter) {
+               mono_class_setup_fields (klass);
                /* start from the first */
                if (klass->field.count) {
                        return *iter = &klass->fields [0];
@@ -4235,7 +4629,7 @@ mono_class_get_exception_for_failure (MonoClass *klass)
                MonoDomain *domain = mono_domain_get ();
                MonoSecurityManager* secman = mono_security_manager_get_methods ();
                MonoMethod *method = klass->exception_data;
-               guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_CLASS : MONO_METADATA_INHERITANCEDEMAND_METHOD;
+               guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
                MonoObject *exc = NULL;
                gpointer args [4];