2004-02-09 Martin Baulig <martin@ximian.com>
[mono.git] / mono / metadata / class.c
index d868b7820963c72c6e40de5579e8fb6cb6d18b13..6b8d75728face562a7abdf015799acb7d0a052bf 100644 (file)
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 #include <signal.h>
 #include <mono/metadata/image.h>
+#include <mono/metadata/assembly.h>
 #include <mono/metadata/cil-coff.h>
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/reflection.h>
 #include <mono/os/gc_wrapper.h>
 
-/*
- * Uncomment this to enable GC aware auto layout: in this mode, reference
- * fields are grouped together inside objects, increasing collector 
- * performance.
- * Requires that all classes whose layout is known to native code be annotated
- * with [StructLayout (LayoutKind.Sequential)]
- */
-//#define GC_AWARE_AUTO_LAYOUT
-
-#define CSIZE(x) (sizeof (x) / 4)
-
 MonoStats mono_stats;
 
 gboolean mono_print_vtable = FALSE;
@@ -179,23 +169,63 @@ mono_type_get_name (MonoType *type)
        return g_string_free (result, FALSE);
 }
 
-static MonoType*
-inflate_generic_type (MonoType *type, MonoGenericInst *tgen, MonoGenericInst *mgen)
+gboolean
+mono_class_is_open_constructed_type (MonoType *t)
+{
+       switch (t->type) {
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR:
+               return TRUE;
+       case MONO_TYPE_SZARRAY:
+               return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
+       case MONO_TYPE_ARRAY:
+               return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
+       case MONO_TYPE_PTR:
+               return mono_class_is_open_constructed_type (t->data.type);
+       case MONO_TYPE_GENERICINST: {
+               MonoGenericInst *ginst = t->data.generic_inst;
+               int i;
+
+               if (mono_class_is_open_constructed_type (ginst->generic_type))
+                       return TRUE;
+               for (i = 0; i < ginst->type_argc; i++)
+                       if (mono_class_is_open_constructed_type (ginst->type_argv [i]))
+                               return TRUE;
+               return FALSE;
+       }
+       default:
+               return FALSE;
+       }
+}
+
+MonoType*
+mono_class_inflate_generic_type (MonoType *type, MonoGenericInst *ginst,
+                                MonoGenericMethod *gmethod)
 {
        switch (type->type) {
        case MONO_TYPE_MVAR:
-               return dup_type (mgen->type_argv [type->data.type_param]);
+               if (gmethod && gmethod->mtype_argv)
+                       return dup_type (gmethod->mtype_argv [type->data.generic_param->num]);
+               else
+                       return type;
        case MONO_TYPE_VAR:
-               /*g_print ("inflating var %d to %s\n", type->data.type_param, mono_type_get_name (tgen->type_argv [type->data.type_param]));*/
-               return dup_type (tgen->type_argv [type->data.type_param]);
+               if (ginst) {
+                       MonoType *t = ginst->type_argv [type->data.generic_param->num];
+
+                       if ((t->type == MONO_TYPE_VAR) || (t->type == MONO_TYPE_MVAR))
+                               return type;
+                       else
+                               return dup_type (t);
+               } else
+                       return type;
        case MONO_TYPE_SZARRAY: {
                MonoClass *eclass = type->data.klass;
                MonoClass *nclass;
                MonoType *nt;
-               if (eclass->byval_arg.type == MONO_TYPE_MVAR) {
-                       nclass = mono_class_from_mono_type (mgen->type_argv [eclass->byval_arg.data.type_param]);
-               } else if (eclass->byval_arg.type == MONO_TYPE_VAR) {
-                       nclass = mono_class_from_mono_type (tgen->type_argv [eclass->byval_arg.data.type_param]);
+               if ((eclass->byval_arg.type == MONO_TYPE_MVAR) && gmethod) {
+                       nclass = mono_class_from_mono_type (gmethod->mtype_argv [eclass->byval_arg.data.generic_param->num]);
+               } else if ((eclass->byval_arg.type == MONO_TYPE_VAR) && ginst) {
+                       nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]);
                } else {
                        return type;
                }
@@ -203,6 +233,26 @@ inflate_generic_type (MonoType *type, MonoGenericInst *tgen, MonoGenericInst *mg
                nt->data.klass = nclass;
                return nt;
        }
+       case MONO_TYPE_GENERICINST: {
+               MonoGenericInst *oginst = type->data.generic_inst;
+               MonoGenericInst *nginst;
+               MonoType *nt;
+               int i;
+
+               nginst = g_new0 (MonoGenericInst, 1);
+               *nginst = *oginst;
+
+               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, ginst, gmethod);
+               };
+
+               nt = dup_type (type);
+               nt->data.generic_inst = nginst;
+               return nt;
+       }
        default:
                return type;
        }
@@ -210,23 +260,26 @@ inflate_generic_type (MonoType *type, MonoGenericInst *tgen, MonoGenericInst *mg
 }
 
 static MonoMethodSignature*
-inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericInst *tgen, MonoGenericInst *mgen)
+inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig,
+                          MonoGenericMethod *gmethod)
 {
        MonoMethodSignature *res;
        int i;
        res = mono_metadata_signature_alloc (image, sig->param_count);
-       res->ret = inflate_generic_type (sig->ret, tgen, mgen);
-       for (i = 0; i < sig->param_count; ++i) {
-               res->params [i] = inflate_generic_type (sig->params [i], tgen, mgen);
-       }
+       res->ret = mono_class_inflate_generic_type (sig->ret, gmethod->generic_inst, gmethod);
+       for (i = 0; i < sig->param_count; ++i)
+               res->params [i] = mono_class_inflate_generic_type (sig->params [i],
+                                                                  gmethod->generic_inst,
+                                                                  gmethod);
        res->hasthis = sig->hasthis;
        res->explicit_this = sig->explicit_this;
        res->call_convention = sig->call_convention;
+       res->generic_param_count = sig->generic_param_count;
        return res;
 }
 
 static MonoMethodHeader*
-inflate_generic_header (MonoMethodHeader *header, MonoGenericInst *tgen, MonoGenericInst *mgen)
+inflate_generic_header (MonoMethodHeader *header, MonoGenericMethod *gmethod)
 {
        MonoMethodHeader *res;
        int i;
@@ -238,14 +291,17 @@ inflate_generic_header (MonoMethodHeader *header, MonoGenericInst *tgen, MonoGen
        res->init_locals = header->init_locals;
        res->num_locals = header->num_locals;
        res->clauses = header->clauses;
-       for (i = 0; i < header->num_locals; ++i) {
-               res->locals [i] = inflate_generic_type (header->locals [i], tgen, mgen);
-       }
+       res->gen_params = header->gen_params;
+       res->gen_method = gmethod;
+       for (i = 0; i < header->num_locals; ++i)
+               res->locals [i] = mono_class_inflate_generic_type (header->locals [i],
+                                                                  gmethod->generic_inst,
+                                                                  gmethod);
        return res;
 }
 
-static MonoMethod*
-inflate_generic_method (MonoMethod *method, MonoGenericInst *tgen, MonoGenericInst *mgen)
+MonoMethod*
+mono_class_inflate_generic_method (MonoMethod *method, MonoGenericMethod *gmethod)
 {
        MonoMethod *result;
        if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
@@ -256,9 +312,12 @@ inflate_generic_method (MonoMethod *method, MonoGenericInst *tgen, MonoGenericIn
                MonoMethodNormal *nmethod = g_new0 (MonoMethodNormal, 1);
                *nmethod = *(MonoMethodNormal*)method;
                result = (MonoMethod*)nmethod;
-               nmethod->header = inflate_generic_header (((MonoMethodNormal*)method)->header, tgen, mgen);
+               if (nmethod->header)
+                       nmethod->header = inflate_generic_header (nmethod->header, gmethod);
        }
-       result->signature = inflate_generic_signature (method->klass->image, result->signature, tgen, mgen);
+       result->klass = gmethod->klass;
+       result->signature = inflate_generic_signature (
+               method->klass->image, result->signature, gmethod);
        return result;
 }
 
@@ -283,6 +342,7 @@ class_compute_field_layout (MonoClass *class)
        guint32 rva;
        guint32 packing_size = 0;
        gboolean explicit_size;
+       MonoClassField *field;
 
        if (class->size_inited)
                return;
@@ -323,66 +383,56 @@ class_compute_field_layout (MonoClass *class)
        for (i = 0; i < top; i++){
                const char *sig;
                guint32 cols [MONO_FIELD_SIZE];
-               guint32 constant_cols [MONO_CONSTANT_SIZE];
-               guint32 cindex;
                int idx = class->field.first + i;
-               
-               mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
+
+               field = &class->fields [i];
+               mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
                /* The name is needed for fieldrefs */
-               class->fields [i].name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
+               field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
                sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
                mono_metadata_decode_value (sig, &sig);
                /* FIELD signature == 0x06 */
                g_assert (*sig == 0x06);
-               class->fields [i].type = mono_metadata_parse_field_type (
+               field->type = mono_metadata_parse_field_type (
                        m, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
+               if (mono_field_is_deleted (field))
+                       continue;
                if (class->generic_inst) {
-                       class->fields [i].type = inflate_generic_type (class->fields [i].type, class->generic_inst->data.generic_inst, NULL);
-                       class->fields [i].type->attrs = cols [MONO_FIELD_FLAGS];
+                       field->type = mono_class_inflate_generic_type (field->type, class->generic_inst, NULL);
+                       field->type->attrs = cols [MONO_FIELD_FLAGS];
                }
 
-               class->fields [i].parent = class;
+               field->parent = class;
 
-               if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)) {
-                       if (class->fields [i].type->byref) {
+               if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
+                       if (field->type->byref) {
                                blittable = FALSE;
                        } else {
-                               MonoClass *field_class = mono_class_from_mono_type (class->fields [i].type);
+                               MonoClass *field_class = mono_class_from_mono_type (field->type);
                                if (!field_class || !field_class->blittable)
                                        blittable = FALSE;
                        }
                }
                if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
-                       mono_metadata_field_info (m, idx, &class->fields [i].offset, NULL, NULL);
-                       if (class->fields [i].offset == (guint32)-1)
-                               g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, class->fields [i].name);
+                       mono_metadata_field_info (m, idx, &field->offset, NULL, NULL);
+                       if (field->offset == (guint32)-1)
+                               g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, field->name);
                }
 
                if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
                        mono_metadata_field_info (m, idx, NULL, &rva, NULL);
                        if (!rva)
-                               g_warning ("field %s in %s should have RVA data, but hasn't", class->fields [i].name, class->name);
-                       class->fields [i].data = mono_cli_rva_map (class->image->image_info, rva);
+                               g_warning ("field %s in %s should have RVA data, but hasn't", field->name, class->name);
+                       field->data = mono_cli_rva_map (class->image->image_info, rva);
                }
 
                if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC)) {
-                       class->enum_basetype = class->fields [i].type;
+                       class->enum_basetype = field->type;
                        class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
                        blittable = class->element_class->blittable;
                }
 
-               if ((class->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
-                       (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)) {
-                       cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (class->field.first + i + 1));
-                       if (!cindex) {
-                               g_warning ("constant for field %s:%s not found", class->name, class->fields [i].name);
-                               continue;
-                       }
-                       mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
-                       class->fields [i].def_value = g_new0 (MonoConstant, 1);
-                       class->fields [i].def_value->type = constant_cols [MONO_CONSTANT_TYPE];
-                       class->fields [i].def_value->value = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
-               }
+               /* The def_value of fields is compute lazily during vtable creation */
        }
 
        if (class == mono_defaults.string_class)
@@ -411,6 +461,21 @@ mono_class_layout_fields (MonoClass *class)
        const int top = class->field.count;
        guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
        guint32 pass, passes, real_size;
+       gboolean gc_aware_layout = FALSE;
+       MonoClassField *field;
+
+       /*
+        * Enable GC aware auto layout: in this mode, reference
+        * fields are grouped together inside objects, increasing collector 
+        * performance.
+        * Requires that all classes whose layout is known to native code be annotated
+        * with [StructLayout (LayoutKind.Sequential)]
+        */
+        /* corlib is missing [StructLayout] directives in many places */
+       if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+               if (class->image != mono_defaults.corlib)
+                       gc_aware_layout = TRUE;
+       }
 
        /*
         * Compute field layout and total size (not considering static fields)
@@ -420,11 +485,11 @@ mono_class_layout_fields (MonoClass *class)
        case TYPE_ATTRIBUTE_AUTO_LAYOUT:
        case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
 
-#ifdef GC_AWARE_AUTO_LAYOUT
-               passes = 2;
-#else
-               passes = 1;
-#endif
+               if (gc_aware_layout)
+                       passes = 2;
+               else
+                       passes = 1;
+
                if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
                        passes = 1;
 
@@ -436,13 +501,14 @@ 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 (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
+                               if (mono_field_is_deleted (field))
+                                       continue;
+                               if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
                                        continue;
 
-#ifdef GC_AWARE_AUTO_LAYOUT
-                               /* FIXME: Fix mono_marshal_load_type_info () too */
-                               if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+                               if (gc_aware_layout) {
                                        /* 
                                         * We process fields with reference type in the first pass,
                                         * and fields with non-reference type in the second pass.
@@ -450,7 +516,7 @@ mono_class_layout_fields (MonoClass *class)
                                         * some internal structures, we store GC_MALLOCed memory
                                         * in IntPtr fields...
                                         */
-                                       if (MONO_TYPE_IS_POINTER (class->fields [i].type)) {
+                                       if (MONO_TYPE_IS_POINTER (field->type)) {
                                                if (pass == 1)
                                                        continue;
                                        } else {
@@ -458,23 +524,22 @@ mono_class_layout_fields (MonoClass *class)
                                                        continue;
                                        }
                                }
-#endif
 
                                if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
-                                       (strcmp (class->fields [i].name, "$PRIVATE$") == 0)) {
+                                       (strcmp (field->name, "$PRIVATE$") == 0)) {
                                        /* This field is a hack inserted by MCS to empty structures */
                                        continue;
                                }
 
-                               size = mono_type_size (class->fields [i].type, &align);
+                               size = mono_type_size (field->type, &align);
                        
                                /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
                                align = class->packing_size ? MIN (class->packing_size, align): align;
                                class->min_align = MAX (align, class->min_align);
-                               class->fields [i].offset = real_size;
-                               class->fields [i].offset += align - 1;
-                               class->fields [i].offset &= ~(align - 1);
-                               real_size = class->fields [i].offset + size;
+                               field->offset = real_size;
+                               field->offset += align - 1;
+                               field->offset &= ~(align - 1);
+                               real_size = field->offset + size;
                        }
 
                        class->instance_size = MAX (real_size, class->instance_size);
@@ -489,29 +554,32 @@ mono_class_layout_fields (MonoClass *class)
                real_size = 0;
                for (i = 0; i < top; i++) {
                        int size, align;
+                       field = &class->fields [i];
 
                        /*
                         * There must be info about all the fields in a type if it
                         * uses explicit layout.
                         */
 
-                       if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
+                       if (mono_field_is_deleted (field))
+                               continue;
+                       if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
                                continue;
 
-                       size = mono_type_size (class->fields [i].type, &align);
+                       size = mono_type_size (field->type, &align);
                        
                        /*
-                        * When we get here, class->fields [i].offset is already set by the
+                        * When we get here, field->offset is already set by the
                         * loader (for either runtime fields or fields loaded from metadata).
                         * The offset is from the start of the object: this works for both
                         * classes and valuetypes.
                         */
-                       class->fields [i].offset += sizeof (MonoObject);
+                       field->offset += sizeof (MonoObject);
 
                        /*
                         * Calc max size.
                         */
-                       real_size = MAX (real_size, size + class->fields [i].offset);
+                       real_size = MAX (real_size, size + field->offset);
                }
                class->instance_size = MAX (real_size, class->instance_size);
                break;
@@ -524,15 +592,18 @@ mono_class_layout_fields (MonoClass *class)
         */
        for (i = 0; i < top; i++){
                int size, align;
+               field = &class->fields [i];
                        
-               if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
+               if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
+                       continue;
+               if (mono_field_is_deleted (field))
                        continue;
                        
-               size = mono_type_size (class->fields [i].type, &align);
-               class->fields [i].offset = class->class_size;
-               class->fields [i].offset += align - 1;
-               class->fields [i].offset &= ~(align - 1);
-               class->class_size = class->fields [i].offset + size;
+               size = mono_type_size (field->type, &align);
+               field->offset = class->class_size;
+               field->offset += align - 1;
+               field->offset &= ~(align - 1);
+               class->class_size = field->offset + size;
        }
 }
 
@@ -726,6 +797,9 @@ setup_interface_offsets (MonoClass *class, int cur_slot)
                }
        }
 
+       if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
+               class->interface_offsets [class->interface_id] = cur_slot;
+
        return cur_slot;
 }
 
@@ -899,6 +973,20 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum)
                                        if (im->flags & METHOD_ATTRIBUTE_STATIC)
                                                        continue;
                                        g_assert (io + l <= max_vtsize);
+
+                                       /* 
+                                        * If one of our parents already implements this interface
+                                        * we can inherit the implementation.
+                                        */
+                                       if (!(vtable [io + l])) {
+                                               MonoClass *parent = class->parent;
+
+                                               if ((ic->interface_id <= parent->max_interface_id) && 
+                                                       (parent->interface_offsets [ic->interface_id]) &&
+                                                       parent->vtable)
+                                                       vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
+                                       }
+
                                        if (!(vtable [io + l])) {
                                                for (j = 0; j < onum; ++j) {
                                                        g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name, 
@@ -970,7 +1058,7 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum)
                if (cm->slot < 0)
                        cm->slot = cur_slot++;
 
-               if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
+               if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT) && !cm->signature->generic_param_count)
                        vtable [cm->slot] = cm;
        }
 
@@ -1142,13 +1230,7 @@ mono_class_init (MonoClass *class)
                        class->methods [1] = ctor;
                }
        } else {
-               if (class->generic_inst) {
-                       for (i = 0; i < class->method.count; ++i) {
-                               class->methods [i] = inflate_generic_method (class->methods [i], class->generic_inst->data.generic_inst, NULL);
-                               class->methods [i]->klass = class;
-                               /*g_print ("inflated method %s in %s\n", class->methods [i]->name, class->name);*/
-                       }
-               } else {
+               if (!class->generic_inst && !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,
@@ -1395,6 +1477,15 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
                if (!parent)
                        g_assert_not_reached (); /* FIXME */
 
+               if (parent->generic_inst && !parent->name) {
+                       /*
+                        * If the parent is a generic instance, we may get
+                        * called before it is fully initialized, especially
+                        * before it has its name.
+                        */
+                       return;
+               }
+
                class->marshalbyref = parent->marshalbyref;
                class->contextbound  = parent->contextbound;
                class->delegate  = parent->delegate;
@@ -1519,7 +1610,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
 
        if (tt->rows > tidx){           
-               mono_metadata_decode_row (tt, tidx, cols_next, CSIZE (cols_next));
+               mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
                class->field.last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
                class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
        } else {
@@ -1582,44 +1673,74 @@ get_instantiation_name (const char *name, MonoGenericInst *ginst)
        return g_string_free (res, FALSE);
 }
 
-MonoClass*
-mono_class_from_generic (MonoType *gtype)
+static void
+mono_class_initialize_generic (MonoGenericInst *ginst, gboolean inflate_methods)
 {
-       MonoGenericInst *ginst = gtype->data.generic_inst;
-       MonoClass *gklass = mono_class_from_mono_type (ginst->generic_type);
-       MonoClass *class;
-       MonoImage *image;
+       MonoClass *klass, *gklass, *pklass;
 
-       mono_loader_lock ();
+       if (ginst->initialized || ginst->init_pending)
+               return;
 
-       image = gklass->image;
-       if ((class = g_hash_table_lookup (image->generics_cache, gtype))) {
-               mono_loader_unlock ();
-               return class;
+       gklass = mono_class_from_mono_type (ginst->generic_type);
+       mono_class_init (gklass);
+
+       klass = ginst->klass;
+       klass->name = get_instantiation_name (gklass->name, ginst);
+
+       if (ginst->parent)
+               pklass = mono_class_from_mono_type (ginst->parent);
+       else
+               pklass = gklass->parent;
+
+       mono_class_setup_parent (klass, pklass);
+       mono_class_setup_mono_type (klass);
+
+       if (inflate_methods) {
+               int i;
+
+               klass->field = gklass->field;
+               klass->method = gklass->method;
+               klass->methods = g_new0 (MonoMethod *, klass->method.count);
+
+               for (i = 0; i < klass->method.count; i++) {
+                       MonoGenericMethod *gmethod = g_new0 (MonoGenericMethod, 1);
+
+                       gmethod->klass = klass;
+                       gmethod->generic_method = gklass->methods [i];
+                       gmethod->generic_inst = ginst;
+
+                       klass->methods [i] = mono_class_inflate_generic_method (
+                               gklass->methods [i], gmethod);
+               }
        }
 
+       ginst->initialized = TRUE;
+}
+
+MonoClass*
+mono_class_from_generic (MonoGenericInst *ginst)
+{
+       MonoClass *class, *gklass, *pklass;
+
+       if (ginst->klass) {
+               mono_class_initialize_generic (ginst, TRUE);
+               return ginst->klass;
+       }
+
+       mono_loader_lock ();
+
+       gklass = mono_class_from_mono_type (ginst->generic_type);
        mono_class_init (gklass);
 
-       class = g_malloc0 (sizeof (MonoClass));
+       class = ginst->klass = g_malloc0 (sizeof (MonoClass));
        class->name_space = gklass->name_space;
        class->name = get_instantiation_name (gklass->name, ginst);
-       class->image = image;
+       class->image = gklass->image;
        class->flags = gklass->flags;
 
-       class->generic_inst = gtype;
+       class->generic_inst = ginst;
 
        class->cast_class = class->element_class = class;
-       mono_class_setup_parent (class, gklass->parent);
-       mono_class_setup_mono_type (class);
-
-       class->field = gklass->field;
-       class->method = gklass->method;
-       class->methods = gklass->methods;
-
-       /*g_print ("instantiating class from %s.%s to %s\n", gklass->name_space, gklass->name, class->name);
-       g_print ("methods: %d, fields: %d\n", class->method.count, class->field.count);*/
-
-       g_hash_table_insert (image->generics_cache, gtype, class);
 
        mono_loader_unlock ();
 
@@ -1627,42 +1748,73 @@ mono_class_from_generic (MonoType *gtype)
 }
 
 MonoClass *
-mono_class_from_gen_param (MonoImage *image, gboolean mvar, int type_num, MonoGenericParam *param)
+mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
 {
-       MonoClass *result;
-       int key;
-       static GHashTable *cache = NULL;
+       MonoClass *klass, **ptr;
+       int count, pos, i;
 
-       mono_loader_lock ();
+       if (param->pklass)
+               return param->pklass;
 
-       if (!cache)
-               cache = g_hash_table_new (NULL, NULL);
+       klass = param->pklass = g_new0 (MonoClass, 1);
 
-       key = mvar? 1: 0;
-       key |= type_num << 1;
+       for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
+               ;
 
-       if ((result = g_hash_table_lookup (cache, GINT_TO_POINTER (key)))) {
-               mono_loader_unlock ();
-               return result;
+       pos = 0;
+       if ((count > 0) && !(param->constraints [0]->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+               klass->parent = param->constraints [0];
+               pos++;
+       } else
+               klass->parent = mono_defaults.object_class;
+
+       if (count - pos > 0) {
+               klass->interface_count = count - pos;
+               klass->interfaces = g_new0 (MonoClass *, count - pos);
+               for (i = pos; i < count; i++)
+                       klass->interfaces [i - pos] = param->constraints [i];
        }
-       result = g_new0 (MonoClass, 1);
 
-       result->parent = NULL;
-       result->name = g_strdup_printf ("%s%d", mvar? "!!": "!", type_num);
-       result->name_space = "";
-       result->image = mono_defaults.corlib; 
-       result->inited = TRUE;
-       result->cast_class = result->element_class = result;
-       result->enum_basetype = &result->element_class->byval_arg;
+       klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
+       klass->name_space = "";
+       klass->image = image;
+       klass->cast_class = klass->element_class = klass;
+       klass->enum_basetype = &klass->element_class->byval_arg;
+       klass->flags = TYPE_ATTRIBUTE_INTERFACE | TYPE_ATTRIBUTE_PUBLIC;
 
-       result->this_arg.type = result->byval_arg.type = mvar? MONO_TYPE_MVAR: MONO_TYPE_VAR;
-       result->this_arg.data.type_param = result->byval_arg.data.type_param = type_num;
-       result->this_arg.byref = TRUE;
+       klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
+       klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
+       klass->this_arg.byref = TRUE;
 
-       g_hash_table_insert (cache, GINT_TO_POINTER (key), result);
+       mono_class_init (klass);
 
-       mono_loader_unlock ();
-       return result;
+       return klass;
+}
+
+static MonoClass *
+my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar)
+{
+       MonoClass *klass;
+
+       if (param->pklass)
+               return param->pklass;
+
+       klass = g_new0 (MonoClass, 1);
+
+       klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
+       klass->name_space = "";
+       klass->image = mono_defaults.corlib;
+       klass->cast_class = klass->element_class = klass;
+       klass->enum_basetype = &klass->element_class->byval_arg;
+       klass->flags = TYPE_ATTRIBUTE_INTERFACE | TYPE_ATTRIBUTE_PUBLIC;
+
+       klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
+       klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
+       klass->this_arg.byref = TRUE;
+
+       mono_class_init (klass);
+
+       return klass;
 }
 
 MonoClass *
@@ -1789,7 +1941,7 @@ mono_class_from_mono_type (MonoType *type)
        case MONO_TYPE_TYPEDBYREF:
                return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
        case MONO_TYPE_ARRAY:
-               return mono_array_class_get (type->data.array->eklass, type->data.array->rank);
+               return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
        case MONO_TYPE_PTR:
                return mono_ptr_class_get (type->data.type);
        case MONO_TYPE_FNPTR:
@@ -1800,11 +1952,11 @@ mono_class_from_mono_type (MonoType *type)
        case MONO_TYPE_VALUETYPE:
                return type->data.klass;
        case MONO_TYPE_GENERICINST:
-               return mono_class_from_generic (type);
+               return mono_class_from_generic (type->data.generic_inst);
        case MONO_TYPE_VAR:
-               return mono_class_from_gen_param (NULL, FALSE, type->data.type_param, NULL);
+               return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE);
        case MONO_TYPE_MVAR:
-               return mono_class_from_gen_param (NULL, TRUE, type->data.type_param, NULL);
+               return my_mono_class_from_generic_parameter (type->data.generic_param, TRUE);
        default:
                g_warning ("implement me 0x%02x\n", type->type);
                g_assert_not_reached ();
@@ -1835,27 +1987,29 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
        case MONO_TYPE_PTR:
                class = mono_class_from_mono_type (type->data.type);
                break;
+       case MONO_TYPE_GENERICINST:
+               class = mono_class_from_generic (type->data.generic_inst);
+               break;
        default:
                /* it seems any type can be stored in TypeSpec as well */
                class = mono_class_from_mono_type (type);
                break;
        }
 
-       mono_metadata_free_type (type);
-       
        return class;
 }
 
 /**
- * mono_array_class_get:
+ * mono_bounded_array_class_get:
  * @element_class: element class 
  * @rank: the dimension of the array class
+ * @bounded: whenever the array has non-zero bounds
  *
  * Returns: a class object describing the array with element type @element_type and 
  * dimension @rank. 
  */
 MonoClass *
-mono_array_class_get (MonoClass *eclass, guint32 rank)
+mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
 {
        MonoImage *image;
        MonoClass *class;
@@ -1867,6 +2021,10 @@ mono_array_class_get (MonoClass *eclass, guint32 rank)
 
        g_assert (rank <= 255);
 
+       if (rank > 1)
+               /* bounded only matters for one-dimensional arrays */
+               bounded = FALSE;
+
        image = eclass->image;
 
        mono_loader_lock ();
@@ -1874,7 +2032,7 @@ mono_array_class_get (MonoClass *eclass, guint32 rank)
        if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
                for (; list; list = list->next) {
                        class = list->data;
-                       if (class->rank == rank) {
+                       if ((class->rank == rank) && (class->byval_arg.type == (bounded ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
                                mono_loader_unlock ();
                                return class;
                        }
@@ -1882,7 +2040,7 @@ mono_array_class_get (MonoClass *eclass, guint32 rank)
        }
 
        /* for the building corlib use System.Array from it */
-       if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "corlib") == 0) {
+       if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "mscorlib") == 0) {
                parent = mono_class_from_name (image, "System", "Array");
                corlib_type = TRUE;
        } else {
@@ -1922,7 +2080,7 @@ mono_array_class_get (MonoClass *eclass, guint32 rank)
 
        class->element_class = eclass;
 
-       if (rank > 1) {
+       if ((rank > 1) || bounded) {
                MonoArrayType *at = g_new0 (MonoArrayType, 1);
                class->byval_arg.type = MONO_TYPE_ARRAY;
                class->byval_arg.data.array = at;
@@ -1930,7 +2088,6 @@ mono_array_class_get (MonoClass *eclass, guint32 rank)
                at->rank = rank;
                /* FIXME: complete.... */
        } else {
-               /* FIXME: this is not correct. the lbound could be >0 */
                class->byval_arg.type = MONO_TYPE_SZARRAY;
                class->byval_arg.data.klass = eclass;
        }
@@ -1948,6 +2105,20 @@ mono_array_class_get (MonoClass *eclass, guint32 rank)
        return class;
 }
 
+/**
+ * mono_array_class_get:
+ * @element_class: element class 
+ * @rank: the dimension of the array class
+ *
+ * Returns: a class object describing the array with element type @element_type and 
+ * dimension @rank. 
+ */
+MonoClass *
+mono_array_class_get (MonoClass *eclass, guint32 rank)
+{
+       return mono_bounded_array_class_get (eclass, rank, FALSE);
+}
+
 /**
  * mono_class_instance_size:
  * @klass: a class 
@@ -2100,9 +2271,9 @@ mono_class_get_property_from_name (MonoClass *klass, const char *name)
 MonoClass *
 mono_class_get (MonoImage *image, guint32 type_token)
 {
-       MonoClass *class;
+       MonoClass *class = NULL;
 
-       if (image->assembly->dynamic)
+       if (image->dynamic)
                return mono_lookup_dynamic_token (image, type_token);
 
        switch (type_token & 0xff000000){
@@ -2150,37 +2321,6 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char
        return NULL;
 }
 
-static MonoImage*
-load_file_for_image (MonoImage *image, int fileidx)
-{
-       char *base_dir, *name;
-       MonoImage *res;
-       MonoTableInfo  *t = &image->tables [MONO_TABLE_FILE];
-       const char *fname;
-       guint32 fname_id;
-
-       if (fileidx < 1 || fileidx > t->rows)
-               return NULL;
-       fname_id = mono_metadata_decode_row_col (t, fileidx - 1, MONO_FILE_NAME);
-       fname = mono_metadata_string_heap (image, fname_id);
-       base_dir = g_path_get_dirname (image->name);
-       name = g_build_filename (base_dir, fname, NULL);
-       res = mono_image_open (name, NULL);
-       if (res) {
-               int i;
-               t = &res->tables [MONO_TABLE_MODULEREF];
-               //g_print ("loaded file %s from %s (%p)\n", name, image->name, image->assembly);
-               res->assembly = image->assembly;
-               for (i = 0; i < t->rows; ++i) {
-                       if (res->modules [i] && !res->modules [i]->assembly)
-                               res->modules [i]->assembly = image->assembly;
-               }
-       }
-       g_free (name);
-       g_free (base_dir);
-       return res;
-}
-
 static MonoClass*
 return_nested_in (MonoClass *class, char *nested) {
        MonoClass *found;
@@ -2231,35 +2371,31 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
                token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
 
        mono_loader_unlock ();
-       
-       if (!token) {
+
+       if (!token)
+               return NULL;
+
+       if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
                MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
                guint32 cols [MONO_EXP_TYPE_SIZE];
-               int i;
+               guint32 idx, impl;
 
-               for (i = 0; i < t->rows; ++i) {
-                       const char *ename, *enspace;
-                       mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
-                       ename = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
-                       enspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
-
-                       if (strcmp (name, ename) == 0 && strcmp (name_space, enspace) == 0) {
-                               guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
-                               if ((impl & IMPLEMENTATION_MASK) == IMPLEMENTATION_FILE) {
-                                       loaded_image = load_file_for_image (image, impl >> IMPLEMENTATION_BITS);
-                                       if (!loaded_image)
-                                               return NULL;
-                                       class = mono_class_from_name (loaded_image, name_space, name);
-                                       if (nested)
-                                               return return_nested_in (class, nested);
-                                       return class;
-                               } else {
-                                       g_error ("not yet implemented");
-                               }
-                       }
+               idx = mono_metadata_token_index (token);
+
+               mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
+
+               impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
+               if ((impl & IMPLEMENTATION_MASK) == IMPLEMENTATION_FILE) {
+                       loaded_image = mono_assembly_load_module (image->assembly, impl >> IMPLEMENTATION_BITS);
+                       if (!loaded_image)
+                               return NULL;
+                       class = mono_class_from_name (loaded_image, name_space, name);
+                       if (nested)
+                               return return_nested_in (class, nested);
+                       return class;
+               } else {
+                       g_error ("not yet implemented");
                }
-               /*g_warning ("token not found for %s.%s in image %s", name_space, name, image->name);*/
-               return NULL;
        }
 
        token = MONO_TOKEN_TYPE_DEF | token;
@@ -2321,6 +2457,10 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
                        if (oklass->rank != klass->rank)
                                return FALSE;
 
+                       /* vectors vs. one dimensional arrays */
+                       if (oklass->byval_arg.type != klass->byval_arg.type)
+                               return FALSE;
+
                        eclass = klass->cast_class;
                        eoclass = oklass->cast_class;
 
@@ -2435,7 +2575,7 @@ mono_array_element_size (MonoClass *ac)
 gpointer
 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class)
 {
-       if (image->assembly->dynamic) {
+       if (image->dynamic) {
                gpointer obj = mono_lookup_dynamic_token (image, token);
 
                switch (token & 0xff000000) {