2003-12-04 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / class.c
index ad0b98ce800505363abad6ab91b9722947f15304..1b2011b9b4bc067e68457434b7db94b04f8cef0f 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;
@@ -179,23 +171,60 @@ 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)
 {
        switch (type->type) {
        case MONO_TYPE_MVAR:
-               return dup_type (mgen->type_argv [type->data.generic_param->num]);
-       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.generic_param->num]);
+               if (ginst)
+                       return dup_type (ginst->type_argv [type->data.generic_param->num]);
+               else
+                       return type;
+       case MONO_TYPE_VAR: {
+               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);
+       }
        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.generic_param->num]);
+                       nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]);
                } else if (eclass->byval_arg.type == MONO_TYPE_VAR) {
-                       nclass = mono_class_from_mono_type (tgen->type_argv [eclass->byval_arg.data.generic_param->num]);
+                       nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]);
                } else {
                        return type;
                }
@@ -209,24 +238,25 @@ inflate_generic_type (MonoType *type, MonoGenericInst *tgen, MonoGenericInst *mg
        return type;
 }
 
-static MonoMethodSignature*
-inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericInst *tgen, MonoGenericInst *mgen)
+MonoMethodSignature*
+mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericInst *ginst)
 {
        MonoMethodSignature *res;
        int i;
        res = mono_metadata_signature_alloc (image, sig->param_count);
-       res->ret = inflate_generic_type (sig->ret, tgen, mgen);
+       res->ret = mono_class_inflate_generic_type (sig->ret, ginst);
        for (i = 0; i < sig->param_count; ++i) {
-               res->params [i] = inflate_generic_type (sig->params [i], tgen, mgen);
+               res->params [i] = mono_class_inflate_generic_type (sig->params [i], ginst);
        }
        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, MonoGenericInst *ginst)
 {
        MonoMethodHeader *res;
        int i;
@@ -238,14 +268,16 @@ inflate_generic_header (MonoMethodHeader *header, MonoGenericInst *tgen, MonoGen
        res->init_locals = header->init_locals;
        res->num_locals = header->num_locals;
        res->clauses = header->clauses;
+       res->gen_params = header->gen_params;
+       res->geninst = ginst;
        for (i = 0; i < header->num_locals; ++i) {
-               res->locals [i] = inflate_generic_type (header->locals [i], tgen, mgen);
+               res->locals [i] = mono_class_inflate_generic_type (header->locals [i], ginst);
        }
        return res;
 }
 
-static MonoMethod*
-inflate_generic_method (MonoMethod *method, MonoGenericInst *tgen, MonoGenericInst *mgen)
+MonoMethod*
+mono_class_inflate_generic_method (MonoMethod *method, MonoGenericInst *ginst)
 {
        MonoMethod *result;
        if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
@@ -256,9 +288,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, ginst);
        }
-       result->signature = inflate_generic_signature (method->klass->image, result->signature, tgen, mgen);
+       if (ginst->klass)
+               result->klass = ginst->klass;
+       result->signature = mono_class_inflate_generic_signature (method->klass->image, result->signature, ginst);
        return result;
 }
 
@@ -323,10 +358,8 @@ 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));
                /* The name is needed for fieldrefs */
                class->fields [i].name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
@@ -337,7 +370,7 @@ class_compute_field_layout (MonoClass *class)
                class->fields [i].type = mono_metadata_parse_field_type (
                        m, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
                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 = mono_class_inflate_generic_type (class->fields [i].type, class->generic_inst->data.generic_inst);
                        class->fields [i].type->attrs = cols [MONO_FIELD_FLAGS];
                }
 
@@ -371,18 +404,7 @@ class_compute_field_layout (MonoClass *class)
                        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 +433,20 @@ 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;
+
+       /*
+        * 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 +456,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;
 
@@ -440,9 +476,7 @@ mono_class_layout_fields (MonoClass *class)
                                if (class->fields [i].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.
@@ -458,7 +492,6 @@ mono_class_layout_fields (MonoClass *class)
                                                        continue;
                                        }
                                }
-#endif
 
                                if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
                                        (strcmp (class->fields [i].name, "$PRIVATE$") == 0)) {
@@ -726,6 +759,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;
 }
 
@@ -970,7 +1006,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 +1178,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->methods) {
+               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 +1425,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;
@@ -1583,13 +1622,63 @@ get_instantiation_name (const char *name, MonoGenericInst *ginst)
 }
 
 MonoClass*
-mono_class_from_generic (MonoType *gtype)
+mono_class_create_from_generic (MonoImage *image, MonoType *gtype)
+{
+       MonoClass *gklass = mono_class_from_mono_type (gtype->data.generic_inst->generic_type);
+       MonoClass *class;
+
+       mono_class_init (gklass);
+
+       class = g_new0 (MonoClass, 1);
+       class->name_space = gklass->name_space;
+       class->image = image;
+       class->flags = gklass->flags;
+
+       class->generic_inst = gtype;
+
+       class->cast_class = class->element_class = class;
+
+       return class;
+}
+
+void
+mono_class_initialize_generic (MonoClass *class, gboolean inflate_methods)
+{
+       MonoGenericInst *ginst = class->generic_inst->data.generic_inst;
+       MonoClass *gklass = mono_class_from_mono_type (ginst->generic_type);
+
+       if (class->name)
+               return;
+
+       class->name = get_instantiation_name (gklass->name, ginst);
+
+       if (inflate_methods) {
+               int i;
+
+               mono_class_setup_parent (class, gklass->parent);
+               mono_class_setup_mono_type (class);
+
+               class->field = gklass->field;
+               class->method = gklass->method;
+               class->methods = g_new0 (MonoMethod *, class->method.count);
+               for (i = 0; i < class->method.count; i++)
+                       class->methods [i] = mono_class_inflate_generic_method (gklass->methods [i], ginst);
+       }
+
+       g_hash_table_insert (class->image->generics_cache, ginst->generic_type, class);
+}
+
+MonoClass*
+mono_class_from_generic (MonoType *gtype, gboolean inflate_methods)
 {
        MonoGenericInst *ginst = gtype->data.generic_inst;
        MonoClass *gklass = mono_class_from_mono_type (ginst->generic_type);
        MonoClass *class;
        MonoImage *image;
 
+       if (ginst->klass)
+               return ginst->klass;
+
        mono_loader_lock ();
 
        image = gklass->image;
@@ -1609,15 +1698,19 @@ mono_class_from_generic (MonoType *gtype)
        class->generic_inst = gtype;
 
        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;
+       if (inflate_methods) {
+               int i;
+
+               mono_class_setup_parent (class, gklass->parent);
+               mono_class_setup_mono_type (class);
 
-       /*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);*/
+               class->field = gklass->field;
+               class->method = gklass->method;
+               class->methods = g_new0 (MonoMethod *, class->method.count);
+               for (i = 0; i < class->method.count; i++)
+                       class->methods [i] = mono_class_inflate_generic_method (gklass->methods [i], ginst);
+       }
 
        g_hash_table_insert (image->generics_cache, gtype, class);
 
@@ -1627,52 +1720,84 @@ mono_class_from_generic (MonoType *gtype)
 }
 
 MonoClass *
-mono_class_from_gen_param (MonoGenericParam *param, gboolean mvar)
+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;
 
-       if (param->klass)
-               return param->klass;
+       if (param->pklass)
+               return param->pklass;
 
-       /*
-        * At this point, we're a type parameter which is loaded from reflection.
-        * We create a very minimalistic MonoClass here which just contains that
-        * type parameter's number since we cannot get more information from the
-        * metadata (and also don't need them).
-        */
+       klass = param->pklass = g_new0 (MonoClass, 1);
 
-       mono_loader_lock ();
+       for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
+               ;
 
-       if (!cache)
-               cache = g_hash_table_new (NULL, NULL);
+       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;
 
-       key = mvar? 1: 0;
-       key |= param->num << 1;
+       if (count - pos > 0) {
+               int j;
 
-       if ((result = g_hash_table_lookup (cache, GINT_TO_POINTER (key)))) {
-               mono_loader_unlock ();
-               return result;
+               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];
+                       klass->method.count += param->constraints [i]->method.count;
+               }
+
+               klass->methods = g_new0 (MonoMethod *, klass->method.count);
+               for (i = pos; i < count; i++) {
+                       MonoClass *iface = klass->interfaces [i - pos];
+                       for (j = 0; j < iface->method.count; j++)
+                               klass->methods [klass->method.last++] = iface->methods [j];
+               }
        }
-       result = param->klass = g_new0 (MonoClass, 1);
 
-       result->parent = NULL;
-       result->name = g_strdup_printf ("%s%d", mvar? "!!": "!", param->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;
 
-       result->this_arg.type = result->byval_arg.type = mvar? MONO_TYPE_MVAR: MONO_TYPE_VAR;
-       result->this_arg.data.generic_param = result->byval_arg.data.generic_param = param;
-       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;
+
+       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 *
@@ -1810,14 +1935,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, TRUE);
        case MONO_TYPE_VAR:
+               return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE);
        case MONO_TYPE_MVAR:
-               /* NOTE: Unless this is a dynamic type, only the `num' field is valid in
-                *       `type->data.generic_param'.  For dynamic types, its `klass' field
-                *       points to the already created class.
-                */
-               return mono_class_from_gen_param (type->data.generic_param, type->type == MONO_TYPE_MVAR);
+               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 ();
@@ -1854,8 +1976,6 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
                break;
        }
 
-       mono_metadata_free_type (type);
-       
        return class;
 }
 
@@ -1895,7 +2015,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 {
@@ -2163,37 +2283,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;
@@ -2244,35 +2333,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;