2006-12-15 Miguel de Icaza <miguel@novell.com>
[mono.git] / mono / metadata / class.c
index 847a47920e924605496f6087a21fa3fdeb34aa0b..8bec0f3e97697d5adca56c016fd6ae364b209ef8 100644 (file)
@@ -35,6 +35,9 @@ MonoStats mono_stats;
 
 gboolean mono_print_vtable = FALSE;
 
+/* Function supplied by the runtime to find classes by name using information from the AOT file */
+static MonoGetClassFromName get_class_from_name = NULL;
+
 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
 static void mono_class_create_generic (MonoInflatedGenericClass *gclass);
 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
@@ -75,7 +78,19 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
                /* a typedef in disguise */
                return mono_class_from_name (image, nspace, name);
        case MONO_RESOLTION_SCOPE_MODULEREF:
-               return mono_class_from_name (image->modules [idx - 1], nspace, name);
+               if (image->modules [idx-1])
+                       return mono_class_from_name (image->modules [idx - 1], nspace, name);
+               else {
+                       char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
+                       char *human_name;
+                       
+                       human_name = mono_stringify_assembly_name (&image->assembly->aname);
+                       mono_loader_set_error_type_load (msg, human_name);
+                       g_free (msg);
+                       g_free (human_name);
+               
+                       return NULL;
+               }
        case MONO_RESOLTION_SCOPE_TYPEREF: {
                MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
                GList *tmp;
@@ -114,8 +129,19 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
        /* If this assert fails, it probably means that you haven't installed an assembly load/search hook */
        g_assert (references == image->references);
        g_assert (references [idx - 1]);
-       if (references [idx - 1] == (gpointer)-1)
+
+       /* If the assembly did not load, register this as a type load exception */
+       if (references [idx - 1] == REFERENCE_MISSING){
+               MonoAssemblyName aname;
+               char *human_name;
+               
+               mono_assembly_get_assemblyref (image, idx - 1, &aname);
+               human_name = mono_stringify_assembly_name (&aname);
+               mono_loader_set_error_assembly_load (human_name, image->assembly->ref_only);
+               g_free (human_name);
+               
                return NULL;
+       }
 
        return mono_class_from_name (references [idx - 1]->image, nspace, name);
 }
@@ -194,6 +220,8 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
                mono_type_get_name_recurse (
                        &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
                g_string_append_c (str, '[');
+               if (rank == 1)
+                       g_string_append_c (str, '*');
                for (i = 1; i < rank; i++)
                        g_string_append_c (str, ',');
                g_string_append_c (str, ']');
@@ -716,7 +744,6 @@ mono_class_find_enum_basetype (MonoClass *class)
 {
        MonoImage *m = class->image; 
        const int top = class->field.count;
-       MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
        int i;
 
        g_assert (class->enumtype);
@@ -731,7 +758,8 @@ mono_class_find_enum_basetype (MonoClass *class)
                MonoGenericContainer *container = NULL;
                MonoType *ftype;
 
-               mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
+               /* class->field.first and idx points into the fieldptr table */
+               mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
                sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
                mono_metadata_decode_value (sig, &sig);
                /* FIELD signature == 0x06 */
@@ -772,7 +800,6 @@ mono_class_setup_fields (MonoClass *class)
        MonoImage *m = class->image; 
        int top = class->field.count;
        guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
-       MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
        int i, blittable = TRUE;
        guint32 real_size = 0;
        guint32 packing_size = 0;
@@ -791,9 +818,12 @@ mono_class_setup_fields (MonoClass *class)
        }
 
        class->instance_size = 0;
-       class->class_size = 0;
+       if (!class->rank)
+               class->sizes.class_size = 0;
 
        if (class->parent) {
+               /* For generic instances, class->parent might not have been initialized */
+               mono_class_init (class->parent);
                if (!class->parent->size_inited)
                        mono_class_setup_fields (class->parent);
                class->instance_size += class->parent->instance_size;
@@ -869,7 +899,8 @@ mono_class_setup_fields (MonoClass *class)
                        const char *sig;
                        guint32 cols [MONO_FIELD_SIZE];
 
-                       mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
+                       /* class->field.first and idx points into the fieldptr table */
+                       mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
                        /* The name is needed for fieldrefs */
                        field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
                        sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
@@ -879,7 +910,7 @@ mono_class_setup_fields (MonoClass *class)
                        field->type = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
                        if (!field->type) {
                                mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
-                               continue;
+                               break;
                        }
                        if (mono_field_is_deleted (field))
                                continue;
@@ -933,6 +964,8 @@ mono_class_setup_fields (MonoClass *class)
                class->instance_size = MAX (real_size, class->instance_size);
        }
 
+       if (class->exception_type)
+               return;
        mono_class_layout_fields (class);
 }
 
@@ -971,7 +1004,11 @@ mono_class_has_references (MonoClass *klass)
 }
 
 /* useful until we keep track of gc-references in corlib etc. */
+#ifdef HAVE_SGEN_GC
+#define IS_GC_REFERENCE(t) FALSE
+#else
 #define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U || (t)->type == MONO_TYPE_I || (t)->type == MONO_TYPE_PTR)
+#endif
 
 /*
  * mono_class_layout_fields:
@@ -1083,7 +1120,8 @@ mono_class_layout_fields (MonoClass *class)
 
                for (pass = 0; pass < passes; ++pass) {
                        for (i = 0; i < top; i++){
-                               int size, align;
+                               guint32 size, align;
+                               MonoType *ftype;
 
                                field = &class->fields [i];
 
@@ -1119,6 +1157,13 @@ mono_class_layout_fields (MonoClass *class)
                        
                                /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
                                align = class->packing_size ? MIN (class->packing_size, align): align;
+                               /* if the field has managed references, we need to force-align it
+                                * see bug #77788
+                                */
+                               ftype = mono_type_get_underlying_type (field->type);
+                               if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+                                       align = sizeof (gpointer);
+
                                class->min_align = MAX (align, class->min_align);
                                field->offset = real_size;
                                field->offset += align - 1;
@@ -1137,7 +1182,8 @@ mono_class_layout_fields (MonoClass *class)
        case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
                real_size = 0;
                for (i = 0; i < top; i++) {
-                       int size, align;
+                       guint32 size, align;
+                       MonoType *ftype;
 
                        field = &class->fields [i];
 
@@ -1160,6 +1206,12 @@ mono_class_layout_fields (MonoClass *class)
                         * classes and valuetypes.
                         */
                        field->offset += sizeof (MonoObject);
+                       ftype = mono_type_get_underlying_type (field->type);
+                       if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
+                               if (field->offset % sizeof (gpointer)) {
+                                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                               }
+                       }
 
                        /*
                         * Calc max size.
@@ -1170,13 +1222,23 @@ mono_class_layout_fields (MonoClass *class)
                break;
        }
 
+       if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
+               /*
+                * For small structs, set min_align to at least the struct size, since the
+                * JIT memset/memcpy code assumes this and generates unaligned accesses
+                * otherwise. See #78990 for a testcase.
+                */
+               if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
+                       class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
+       }
+
        class->size_inited = 1;
 
        /*
         * Compute static field layout and size
         */
        for (i = 0; i < top; i++){
-               int size, align;
+               guint32 size, align;
 
                field = &class->fields [i];
                        
@@ -1186,10 +1248,10 @@ mono_class_layout_fields (MonoClass *class)
                        continue;
 
                size = mono_type_size (field->type, &align);
-               field->offset = class->class_size;
+               field->offset = class->sizes.class_size;
                field->offset += align - 1;
                field->offset &= ~(align - 1);
-               class->class_size = field->offset + size;
+               class->sizes.class_size = field->offset + size;
        }
 }
 
@@ -1224,7 +1286,8 @@ mono_class_setup_methods (MonoClass *class)
        if (!class->methods) {
                methods = mono_mempool_alloc (class->image->mempool, sizeof (MonoMethod*) * class->method.count);
                for (i = 0; i < class->method.count; ++i) {
-                       methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
+                       int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
+                       methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
                }
        }
 
@@ -1244,7 +1307,6 @@ mono_class_setup_properties (MonoClass *class)
 {
        guint startm, endm, i, j;
        guint32 cols [MONO_PROPERTY_SIZE];
-       MonoTableInfo *pt = &class->image->tables [MONO_TABLE_PROPERTY];
        MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
        MonoProperty *properties;
        guint32 last;
@@ -1267,20 +1329,29 @@ mono_class_setup_properties (MonoClass *class)
 
        properties = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoProperty) * class->property.count);
        for (i = class->property.first; i < last; ++i) {
-               mono_metadata_decode_row (pt, i, cols, MONO_PROPERTY_SIZE);
+               mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
                properties [i - class->property.first].parent = class;
                properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
                properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
 
                startm = mono_metadata_methods_from_property (class->image, i, &endm);
                for (j = startm; j < endm; ++j) {
+                       MonoMethod *method;
+
                        mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
+
+                       if (class->image->uncompressed_metadata)
+                               /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
+                               method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
+                       else
+                               method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+
                        switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
                        case METHOD_SEMANTIC_SETTER:
-                               properties [i - class->property.first].set = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+                               properties [i - class->property.first].set = method;
                                break;
                        case METHOD_SEMANTIC_GETTER:
-                               properties [i - class->property.first].get = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+                               properties [i - class->property.first].get = method;
                                break;
                        default:
                                break;
@@ -1348,7 +1419,6 @@ mono_class_setup_events (MonoClass *class)
 {
        guint startm, endm, i, j;
        guint32 cols [MONO_EVENT_SIZE];
-       MonoTableInfo *pt = &class->image->tables [MONO_TABLE_EVENT];
        MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
        guint32 last;
        MonoEvent *events;
@@ -1393,24 +1463,33 @@ mono_class_setup_events (MonoClass *class)
        events = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoEvent) * class->event.count);
        for (i = class->event.first; i < last; ++i) {
                MonoEvent *event = &events [i - class->event.first];
-                       
-               mono_metadata_decode_row (pt, i, cols, MONO_EVENT_SIZE);
+
+               mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
                event->parent = class;
                event->attrs = cols [MONO_EVENT_FLAGS];
                event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
 
                startm = mono_metadata_methods_from_event (class->image, i, &endm);
                for (j = startm; j < endm; ++j) {
+                       MonoMethod *method;
+
                        mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
+
+                       if (class->image->uncompressed_metadata)
+                               /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
+                               method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
+                       else
+                               method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+
                        switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
                        case METHOD_SEMANTIC_ADD_ON:
-                               event->add = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+                               event->add = method;
                                break;
                        case METHOD_SEMANTIC_REMOVE_ON:
-                               event->remove = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+                               event->remove = method;
                                break;
                        case METHOD_SEMANTIC_FIRE:
-                               event->raise = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+                               event->raise = method;
                                break;
                        case METHOD_SEMANTIC_OTHER: {
                                int n = 0;
@@ -1422,7 +1501,7 @@ mono_class_setup_events (MonoClass *class)
                                                n++;
                                        event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
                                }
-                               event->other [n] = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+                               event->other [n] = method;
                                /* NULL terminated */
                                event->other [n + 1] = NULL;
                                break;
@@ -1715,6 +1794,7 @@ mono_class_setup_vtable (MonoClass *class)
        MonoGenericContext *context;
        guint32 type_token;
        int onum = 0;
+       gboolean ok = TRUE;
 
        if (class->vtable)
                return;
@@ -1731,6 +1811,8 @@ mono_class_setup_vtable (MonoClass *class)
                return;
        }
 
+       mono_stats.generic_vtable_count ++;
+
        if (class->generic_class) {
                context = class->generic_class->context;
                type_token = class->generic_class->container_class->type_token;
@@ -1741,13 +1823,19 @@ mono_class_setup_vtable (MonoClass *class)
 
        if (class->image->dynamic)
                mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
-       else
-               mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
+       else {
+               /* The following call fails if there are missing methods in the type */
+               ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
+       }
 
-       mono_class_setup_vtable_general (class, overrides, onum);
+       if (ok)
+               mono_class_setup_vtable_general (class, overrides, onum);
+               
        g_free (overrides);
 
        mono_loader_unlock ();
+
+       return;
 }
 
 /*
@@ -1970,11 +2058,14 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                         */
                                        if (!(vtable [io + l])) {
                                                MonoClass *parent = class->parent;
-
-                                               if ((ic->interface_id <= parent->max_interface_id) && 
-                                                       (parent->interface_offsets [ic->interface_id] != -1) &&
-                                                       parent->vtable)
-                                                       vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
+                                               
+                                               for (; parent; parent = parent->parent) {
+                                                       if ((ic->interface_id <= parent->max_interface_id) && 
+                                                                       (parent->interface_offsets [ic->interface_id] != -1) &&
+                                                                       parent->vtable) {
+                                                               vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
+                                                       }
+                                               }
                                        }
 
                                        if (!(vtable [io + l])) {
@@ -2037,10 +2128,21 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                int j;
                                for (j = 0; j < k->method.count; ++j) {
                                        MonoMethod *m1 = k->methods [j];
+                                       MonoMethodSignature *cmsig, *m1sig;
+
                                        if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
                                                continue;
+
+                                       cmsig = mono_method_signature (cm);
+                                       m1sig = mono_method_signature (m1);
+
+                                       if (!cmsig || !m1sig) {
+                                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                                               return;
+                                       }
+
                                        if (!strcmp(cm->name, m1->name) && 
-                                           mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (m1))) {
+                                           mono_metadata_signature_equal (cmsig, m1sig)) {
 
                                                /* CAS - SecurityAction.InheritanceDemand */
                                                if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
@@ -2106,8 +2208,13 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
        } else
                class->vtable_size = cur_slot;
 
-       class->vtable = mono_mempool_alloc0 (class->image->mempool, sizeof (gpointer) * class->vtable_size);
-       memcpy (class->vtable, vtable,  sizeof (gpointer) * class->vtable_size);
+       /* Try to share the vtable with our parent. */
+       if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
+               class->vtable = class->parent->vtable;
+       } else {
+               class->vtable = mono_mempool_alloc0 (class->image->mempool, sizeof (gpointer) * class->vtable_size);
+               memcpy (class->vtable, vtable,  sizeof (gpointer) * class->vtable_size);
+       }
 
        if (mono_print_vtable) {
                int icount = 0;
@@ -2193,6 +2300,46 @@ g_list_prepend_mempool (GList* l, MonoMemPool* mp, gpointer datum)
        return n;
 }
 
+static void
+setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, int pos)
+{
+       MonoGenericContext *context;
+       int i;
+
+       context = g_new0 (MonoGenericContext, 1);
+       context->container = iface->generic_class->context->container;
+       context->gmethod = g_new0 (MonoGenericMethod, 1);
+       context->gmethod->generic_class = iface->generic_class;
+       context->gmethod->inst = iface->generic_class->inst;
+
+       for (i = 0; i < class->parent->method.count; i++) {
+               MonoMethod *m = class->parent->methods [i];
+               MonoMethod *inflated;
+               const char *mname, *iname;
+               gchar *name;
+
+               if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
+                       iname = "System.Collections.Generic.ICollection`1.";
+                       mname = m->name + 27;
+               } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
+                       iname = "System.Collections.Generic.IEnumerable`1.";
+                       mname = m->name + 27;
+               } else if (!strncmp (m->name, "InternalArray__", 15)) {
+                       iname = "System.Collections.Generic.IList`1.";
+                       mname = m->name + 15;
+               } else {
+                       continue;
+               }
+
+               name = mono_mempool_alloc (class->image->mempool, strlen (iname) + strlen (mname) + 1);
+               strcpy (name, iname);
+               strcpy (name + strlen (iname), mname);
+
+               inflated = mono_class_inflate_generic_method (m, context);
+               class->methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, name, inflated);
+       }
+}
+
 /**
  * mono_class_init:
  * @class: the class to initialize
@@ -2200,19 +2347,23 @@ g_list_prepend_mempool (GList* l, MonoMemPool* mp, gpointer datum)
  * compute the instance_size, class_size and other infos that cannot be 
  * computed at mono_class_get() time. Also compute a generic vtable and 
  * the method slot numbers. We use this infos later to create a domain
- * specific vtable.  
+ * specific vtable.
+ *
+ * Returns TRUE on success or FALSE if there was a problem in loading
+ * the type (incorrect assemblies, missing assemblies, methods, etc). 
  */
-void
+gboolean
 mono_class_init (MonoClass *class)
 {
        int i;
        MonoCachedClassInfo cached_info;
        gboolean has_cached_info;
-
+       int class_init_ok = TRUE;
+       
        g_assert (class);
 
        if (class->inited)
-               return;
+               return TRUE;
 
        /*g_print ("Init class %s\n", class->name);*/
 
@@ -2222,7 +2373,7 @@ mono_class_init (MonoClass *class)
        if (class->inited) {
                mono_loader_unlock ();
                /* Somebody might have gotten in before us */
-               return;
+               return TRUE;
        }
 
        if (class->init_pending) {
@@ -2316,22 +2467,42 @@ mono_class_init (MonoClass *class)
         */
        if (has_cached_info) {
                class->instance_size = cached_info.instance_size;
-               class->class_size = cached_info.class_size;
+               class->sizes.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;
+               class->no_special_static_fields = cached_info.no_special_static_fields;
        }
        else
-               if (!class->size_inited)
+               if (!class->size_inited){
                        mono_class_setup_fields (class);
+                       if (class->exception_type || mono_loader_get_last_error ()){
+                               class_init_ok = FALSE;
+                               goto leave;
+                       }
+               }
+                               
 
        /* initialize method pointers */
        if (class->rank) {
                MonoMethod *ctor;
                MonoMethodSignature *sig;
-               class->method.count = class->rank > 1? 2: 1;
+               int count_generic = 0, first_generic = 0;
+
+               class->method.count = (class->rank > 1? 2: 1);
+
+               if (class->interface_count) {
+                       for (i = 0; i < class->parent->method.count; i++) {
+                               MonoMethod *m = class->parent->methods [i];
+                               if (!strncmp (m->name, "InternalArray__", 15))
+                                       count_generic++;
+                       }
+                       first_generic = class->method.count;
+                       class->method.count += class->interface_count * count_generic;
+               }
+
                sig = mono_metadata_signature_alloc (class->image, class->rank);
                sig->ret = &mono_defaults.void_class->byval_arg;
                sig->pinvoke = TRUE;
@@ -2363,6 +2534,9 @@ mono_class_init (MonoClass *class)
                        ctor->slot = -1;
                        class->methods [1] = ctor;
                }
+
+               for (i = 0; i < class->interface_count; i++)
+                       setup_generic_array_ifaces (class, class->interfaces [i], first_generic + i * count_generic);
        }
 
        mono_class_setup_supertypes (class);
@@ -2391,7 +2565,12 @@ mono_class_init (MonoClass *class)
        }
        else {
                mono_class_setup_vtable (class);
-       
+
+               if (class->exception_type || mono_loader_get_last_error ()){
+                       class_init_ok = FALSE;
+                       goto leave;
+               }
+
                class->ghcimpl = 1;
                if (class->parent) { 
                        MonoMethod *cmethod = class->vtable [ghc_slot];
@@ -2431,13 +2610,16 @@ mono_class_init (MonoClass *class)
                setup_interface_offsets (class, 0);
        }
 
+ leave:
        class->inited = 1;
        class->init_pending = 0;
-       
+
        mono_loader_unlock ();
 
        if (mono_debugger_class_init_func)
                mono_debugger_class_init_func (class);
+
+       return class_init_ok;
 }
 
 /*
@@ -2586,8 +2768,14 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
        }
 
        if (!MONO_CLASS_IS_INTERFACE (class)) {
+               /* Imported COM Objects always derive from __ComObject. */
+               if (MONO_CLASS_IS_IMPORT (class)) {
+                       if (parent == mono_defaults.object_class)
+                               parent = mono_defaults.com_object_class;
+               }
                class->parent = parent;
 
+
                if (!parent)
                        g_assert_not_reached (); /* FIXME */
 
@@ -2603,6 +2791,10 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
                class->marshalbyref = parent->marshalbyref;
                class->contextbound  = parent->contextbound;
                class->delegate  = parent->delegate;
+               if (MONO_CLASS_IS_IMPORT (class))
+                       class->is_com_object = 1;
+               else
+                       class->is_com_object = parent->is_com_object;
                
                if (system_namespace) {
                        if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
@@ -2793,6 +2985,11 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        if (cols [MONO_TYPEDEF_EXTENDS]) {
                parent = mono_class_get_full (
                        image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
+               if (parent == NULL){
+                       g_hash_table_remove (image->class_cache, GUINT_TO_POINTER (type_token));
+                       mono_loader_unlock ();
+                       return NULL;
+               }
        }
 
        /* do this early so it's available for interfaces in setup_mono_type () */
@@ -2805,7 +3002,11 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        mono_class_setup_mono_type (class);
 
        if (!class->enumtype) {
-               mono_metadata_interfaces_from_typedef_full (image, type_token, &interfaces, &icount, context);
+               if (!mono_metadata_interfaces_from_typedef_full (
+                           image, type_token, &interfaces, &icount, context)){
+                       mono_loader_unlock ();
+                       return NULL;
+               }
 
                class->interfaces = interfaces;
                class->interface_count = icount;
@@ -2943,7 +3144,7 @@ mono_class_create_generic (MonoInflatedGenericClass *gclass)
 
        if (gclass->generic_class.is_dynamic) {
                klass->instance_size = gklass->instance_size;
-               klass->class_size = gklass->class_size;
+               klass->sizes.class_size = gklass->sizes.class_size;
                klass->size_inited = 1;
                klass->inited = 1;
 
@@ -3119,7 +3320,7 @@ mono_fnptr_class_get (MonoMethodSignature *sig)
        result->parent = NULL; /* no parent for PTR types */
        result->name_space = "System";
        result->name = "MonoFNPtrFakeClass";
-       result->image = NULL; /* need to fix... */
+       result->image = mono_defaults.corlib; /* need to fix... */
        result->inited = TRUE;
        result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
        /* Can pointers get boxed? */
@@ -3214,11 +3415,20 @@ mono_class_from_mono_type (MonoType *type)
 /**
  * @image: context where the image is created
  * @type_spec:  typespec token
+ * @context: the generic context used to evaluate generic instantiations in
  */
 static MonoClass *
-mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
+mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context)
 {
-       return mono_class_from_mono_type (mono_type_create_from_typespec (image, type_spec));
+       MonoType *t = mono_type_create_from_typespec (image, type_spec);
+       if (!t)
+               return NULL;
+       if (context && (context->gclass || context->gmethod)) {
+               MonoType *inflated = inflate_generic_type (t, context);
+               if (inflated)
+                       t = inflated;
+       }
+       return mono_class_from_mono_type (t);
 }
 
 /**
@@ -3257,7 +3467,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
        if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
                for (; list; list = list->next) {
                        class = list->data;
-                       if ((class->rank == rank) && (class->byval_arg.type == (bounded ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
+                       if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
                                mono_loader_unlock ();
                                return class;
                        }
@@ -3268,18 +3478,6 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
        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)
@@ -3306,8 +3504,70 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
                (eclass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
        class->parent = parent;
        class->instance_size = mono_class_instance_size (class->parent);
-       class->class_size = 0;
+       class->sizes.element_size = mono_class_array_element_size (eclass);
        mono_class_setup_supertypes (class);
+
+       if (mono_defaults.generic_ilist_class) {
+               MonoClass *fclass = NULL;
+               int i;
+
+               if (eclass->valuetype) {
+                       if (eclass == mono_defaults.int16_class)
+                               fclass = mono_defaults.uint16_class;
+                       if (eclass == mono_defaults.uint16_class)
+                               fclass = mono_defaults.int16_class;
+                       if (eclass == mono_defaults.int32_class)
+                               fclass = mono_defaults.uint32_class;
+                       if (eclass == mono_defaults.uint32_class)
+                               fclass = mono_defaults.int32_class;
+                       if (eclass == mono_defaults.int64_class)
+                               fclass = mono_defaults.uint64_class;
+                       if (eclass == mono_defaults.uint64_class)
+                               fclass = mono_defaults.int64_class;
+                       if (eclass == mono_defaults.byte_class)
+                               fclass = mono_defaults.sbyte_class;
+                       if (eclass == mono_defaults.sbyte_class)
+                               fclass = mono_defaults.byte_class;
+
+                       class->interface_count = fclass ? 2 : 1;
+               } else if (MONO_CLASS_IS_INTERFACE (eclass)) {
+                       class->interface_count = 2 + eclass->interface_count;
+               } else {
+                       class->interface_count = eclass->idepth + eclass->interface_count;
+               }
+
+               class->interfaces = g_new0 (MonoClass *, class->interface_count);
+
+               for (i = 0; i < class->interface_count; i++) {
+                       MonoType *inflated, **args;
+                       MonoClass *iface;
+
+                       if (eclass->valuetype)
+                               iface = (i == 0) ? eclass : fclass;
+                       else if (MONO_CLASS_IS_INTERFACE (eclass)) {
+                               if (i == 0)
+                                       iface = mono_defaults.object_class;
+                               else if (i == 1)
+                                       iface = eclass;
+                               else
+                                       iface = eclass->interfaces [i - 2];
+                       } else {
+                               if (i < eclass->idepth)
+                                       iface = eclass->supertypes [i];
+                               else
+                                       iface = eclass->interfaces [i - eclass->idepth];
+                       }
+
+                       args = g_new0 (MonoType *, 1);
+                       args [0] = &iface->byval_arg;
+
+                       inflated = mono_class_bind_generic_parameters (
+                               &mono_defaults.generic_ilist_class->byval_arg, 1, args);
+
+                       class->interfaces [i] = mono_class_from_mono_type (inflated);
+               }
+       }
+
        if (eclass->generic_class)
                mono_class_init (eclass);
        if (!eclass->size_inited)
@@ -3433,7 +3693,12 @@ mono_class_data_size (MonoClass *klass)
        if (!klass->inited)
                mono_class_init (klass);
 
-       return klass->class_size;
+       /* in arrays, sizes.class_size is unioned with element_size
+        * and arrays have no static fields
+        */
+       if (klass->rank)
+               return 0;
+       return klass->sizes.class_size;
 }
 
 /*
@@ -3447,9 +3712,23 @@ mono_class_get_field_idx (MonoClass *class, int idx)
        mono_class_setup_fields_locking (class);
 
        while (class) {
-               if (class->field.count) {
-                       if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
-                               return &class->fields [idx - class->field.first];
+               if (class->image->uncompressed_metadata) {
+                       /* 
+                        * class->field.first points to the FieldPtr table, while idx points into the
+                        * Field table, so we have to do a search.
+                        */
+                       const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
+                       int i;
+
+                       for (i = 0; i < class->field.count; ++i)
+                               if (class->fields [i].name == name)
+                                       return &class->fields [i];
+                       g_assert_not_reached ();
+               } else {                        
+                       if (class->field.count) {
+                               if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
+                                       return &class->fields [idx - class->field.first];
+                               }
                        }
                }
                class = class->parent;
@@ -3519,8 +3798,13 @@ mono_class_get_field_token (MonoClassField *field)
        mono_class_setup_fields_locking (klass);
        while (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);
+                       if (&klass->fields [i] == field) {
+                               int idx = klass->field.first + i + 1;
+
+                               if (klass->image->uncompressed_metadata)
+                                       idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
+                               return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
+                       }
                }
                klass = klass->parent;
        }
@@ -3675,14 +3959,15 @@ mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
 }
 
 /**
- * mono_class_get:
+ * mono_class_get_full:
  * @image: the image where the class resides
  * @type_token: the token for the class
+ * @context: the generic context used to evaluate generic instantiations in
  *
  * Returns: the MonoClass that represents @type_token in @image
  */
 MonoClass *
-mono_class_get (MonoImage *image, guint32 type_token)
+mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
 {
        MonoClass *class = NULL;
 
@@ -3697,7 +3982,7 @@ mono_class_get (MonoImage *image, guint32 type_token)
                class = mono_class_from_typeref (image, type_token);
                break;
        case MONO_TOKEN_TYPE_SPEC:
-               class = mono_class_create_from_typespec (image, type_token);
+               class = mono_class_create_from_typespec (image, type_token, context);
                break;
        default:
                g_warning ("unknown token type %x", type_token & 0xff000000);
@@ -3714,19 +3999,108 @@ mono_class_get (MonoImage *image, guint32 type_token)
 }
 
 MonoClass *
-mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
+mono_class_get (MonoImage *image, guint32 type_token)
 {
-       MonoClass *class = mono_class_get (image, type_token);
+       return mono_class_get_full (image, type_token, NULL);
+}
 
-       if (!image->dynamic && ((type_token & 0xff000000) == MONO_TOKEN_TYPE_DEF))
-               return class;
+/**
+ * mono_image_init_name_cache:
+ *
+ *  Initializes the class name cache stored in image->name_cache.
+ *
+ * LOCKING: Acquires the loader lock.
+ */
+void
+mono_image_init_name_cache (MonoImage *image)
+{
+       MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
+       guint32 cols [MONO_TYPEDEF_SIZE];
+       const char *name;
+       const char *nspace;
+       guint32 i, visib, nspace_index;
+       GHashTable *name_cache2, *nspace_table;
 
-       if (class && context && (context->gclass || context->gmethod)) {
-               MonoType *inflated = inflate_generic_type (&class->byval_arg, context);
-               if (inflated)
-                       class = mono_class_from_mono_type (inflated);
+       mono_loader_lock ();
+
+       image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
+
+       if (image->dynamic) {
+               mono_loader_unlock ();
+               return;
        }
-       return class;
+
+       /* Temporary hash table to avoid lookups in the nspace_table */
+       name_cache2 = g_hash_table_new (NULL, NULL);
+
+       for (i = 1; i <= t->rows; ++i) {
+               mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
+               /* nested types are accessed from the nesting name */
+               visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+               if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
+                       continue;
+               name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
+               nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
+
+               nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
+               nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
+               if (!nspace_table) {
+                       nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
+                       g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
+                       g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
+                                                                nspace_table);
+               }
+               g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
+       }
+
+       /* Load type names from EXPORTEDTYPES table */
+       {
+               MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
+               guint32 cols [MONO_EXP_TYPE_SIZE];
+               int i;
+
+               for (i = 0; i < t->rows; ++i) {
+                       mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
+                       name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
+                       nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
+
+                       nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
+                       nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
+                       if (!nspace_table) {
+                               nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
+                               g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
+                               g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
+                                                                        nspace_table);
+                       }
+                       g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
+               }
+       }
+
+       g_hash_table_destroy (name_cache2);
+
+       mono_loader_unlock ();
+}
+
+void
+mono_image_add_to_name_cache (MonoImage *image, const char *nspace, 
+                                                         const char *name, guint32 index)
+{
+       GHashTable *nspace_table;
+       GHashTable *name_cache;
+
+       mono_loader_lock ();
+
+       if (!image->name_cache)
+               mono_image_init_name_cache (image);
+
+       name_cache = image->name_cache;
+       if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
+               nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
+               g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
+       }
+       g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
+
+       mono_loader_unlock ();
 }
 
 typedef struct {
@@ -3753,12 +4127,6 @@ find_nocase (gpointer key, gpointer value, gpointer user_data)
  * Obtains a MonoClass with a given namespace and a given name which
  * is located in the given MonoImage.   The namespace and name
  * lookups are case insensitive.
- *
- * You can also pass @NULL to the image, and that will lookup for
- * a type with the given namespace and name in all of the loaded
- * assemblies: notice that since there might be a name clash in this
- * case, passing @NULL is not encouraged if you need a precise type.
- *
  */
 MonoClass *
 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
@@ -3775,6 +4143,9 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char
 
                mono_loader_lock ();
 
+               if (!image->name_cache)
+                       mono_image_init_name_cache (image);
+
                user_data.key = name_space;
                user_data.value = NULL;
                g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
@@ -3845,12 +4216,6 @@ return_nested_in (MonoClass *class, char *nested) {
  *
  * Obtains a MonoClass with a given namespace and a given name which
  * is located in the given MonoImage.   
- *
- * You can also pass `NULL' to the image, and that will lookup for
- * a type with the given namespace and name in all of the loaded
- * assemblies: notice that since there might be a name clash in this
- * case, passing NULL is not encouraged if you need a precise type.
- *
  */
 MonoClass *
 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
@@ -3873,8 +4238,21 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
                name = buf;
        }
 
+       if (get_class_from_name) {
+               gboolean res = get_class_from_name (image, name_space, name, &class);
+               if (res) {
+                       if (nested)
+                               return class ? return_nested_in (class, nested) : NULL;
+                       else
+                               return class;
+               }
+       }
+
        mono_loader_lock ();
 
+       if (!image->name_cache)
+               mono_image_init_name_cache (image);
+
        nspace_table = g_hash_table_lookup (image->name_cache, name_space);
 
        if (nspace_table)
@@ -4143,7 +4521,8 @@ handle_enum:
 gint32
 mono_array_element_size (MonoClass *ac)
 {
-       return mono_class_array_element_size (ac->element_class);
+       g_assert (ac->rank);
+       return ac->sizes.element_size;
 }
 
 gpointer
@@ -4267,6 +4646,12 @@ mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
                return get_cached_class_info (klass, res);
 }
 
+void
+mono_install_get_class_from_name (MonoGetClassFromName func)
+{
+       get_class_from_name = func;
+}
+
 MonoImage*
 mono_class_get_image (MonoClass *klass)
 {
@@ -4411,6 +4796,20 @@ mono_class_get_type (MonoClass *klass)
        return &klass->byval_arg;
 }
 
+/**
+ * mono_class_get_type_token
+ * @klass: the MonoClass to act on
+ *
+ * This method returns type token for the class.
+ *
+ * Returns: the type token for the class.
+ */
+guint32
+mono_class_get_type_token (MonoClass *klass)
+{
+  return klass->type_token;
+}
+
 /**
  * mono_class_get_byref_type:
  * @klass: the MonoClass to act on
@@ -4756,6 +5155,19 @@ mono_field_get_flags (MonoClassField *field)
        return field->type->attrs;
 }
 
+/**
+ * mono_field_get_data;
+ * @field: the MonoClassField to act on
+ *
+ * Returns: pointer to the metadata constant value or to the field
+ * data if it has an RVA flag.
+ */
+const char *
+mono_field_get_data  (MonoClassField *field)
+{
+  return field->data;
+}
+
 /**
  * mono_property_get_name: 
  * @prop: the MonoProperty to act on
@@ -4947,7 +5359,8 @@ mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int p
                        guint32 cols [MONO_METHOD_SIZE];
                        MonoMethod *method;
 
-                       mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_METHOD], klass->method.first + i, cols, MONO_METHOD_SIZE);
+                       /* class->method.first points into the methodptr table */
+                       mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
 
                        if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
                                method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
@@ -5040,10 +5453,29 @@ mono_class_get_exception_for_failure (MonoClass *klass)
                mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
                return (MonoException*) exc;
        }
-       case MONO_EXCEPTION_TYPE_LOAD:
-               return mono_exception_from_name (mono_defaults.corlib, "System", "TypeLoadException");
-       /* TODO - handle other class related failures */
-       default:
+       case MONO_EXCEPTION_TYPE_LOAD: {
+               MonoString *name;
+               MonoException *ex;
+               char *str = mono_type_get_full_name (klass);
+               char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
+               name = mono_string_new (mono_domain_get (), str);
+               g_free (str);
+               ex = mono_get_exception_type_load (name, astr);
+               g_free (astr);
+               return ex;
+       }
+       default: {
+               MonoLoaderError *error;
+               MonoException *ex;
+               
+               error = mono_loader_get_last_error ();
+               if (error != NULL){
+                       ex = mono_loader_error_prepare_exception (error);
+                       return ex;
+               }
+               
+               /* TODO - handle other class related failures */
                return NULL;
        }
+       }
 }