2005-12-23 Dick Porter <dick@ximian.com>
[mono.git] / mono / metadata / class.c
index 9ff11e9bb7d51f0559937d599c021fdea973b8c2..bf74a218511491b8bd2d26c77c2a413eba9b0c85 100644 (file)
@@ -74,11 +74,27 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
        case MONO_RESOLTION_SCOPE_TYPEREF: {
                MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
                GList *tmp;
-               mono_class_init (enclosing);
-               for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
-                       res = tmp->data;
-                       if (strcmp (res->name, name) == 0)
-                               return res;
+
+               if (enclosing->inited) {
+                       /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
+                       for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
+                               res = tmp->data;
+                               if (strcmp (res->name, name) == 0)
+                                       return res;
+                       }
+               } else {
+                       /* Don't call mono_class_init as we might've been called by it recursively */
+                       int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
+                       while (i) {
+                               guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
+                               guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
+                               const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
+
+                               if (strcmp (nname, name) == 0)
+                                       return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested);
+
+                               i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
+                       }
                }
                g_warning ("TypeRef ResolutionScope not yet handled (%d)", idx);
                return NULL;
@@ -107,10 +123,41 @@ dup_type (MonoType* t, const MonoType *original)
        r->byref = original->byref;
        if (t->type == MONO_TYPE_PTR)
                t->data.type = dup_type (t->data.type, original->data.type);
+       else if (t->type == MONO_TYPE_ARRAY)
+               t->data.array = mono_dup_array_type (t->data.array);
+       else if (t->type == MONO_TYPE_FNPTR)
+               t->data.method = mono_metadata_signature_deep_dup (t->data.method);
        mono_stats.generics_metadata_size += sizeof (MonoType);
        return r;
 }
 
+/* Copy everything mono_metadata_free_array free. */
+MonoArrayType *
+mono_dup_array_type (MonoArrayType *a)
+{
+       a = g_memdup (a, sizeof (MonoArrayType));
+       if (a->sizes)
+               a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
+       if (a->lobounds)
+               a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
+       return a;
+}
+
+/* Copy everything mono_metadata_free_method_signature free. */
+MonoMethodSignature*
+mono_metadata_signature_deep_dup (MonoMethodSignature *sig)
+{
+       int i;
+       
+       sig = mono_metadata_signature_dup (sig);
+       
+       sig->ret = dup_type (sig->ret, sig->ret);
+       for (i = 0; i < sig->param_count; ++i)
+               sig->params [i] = dup_type (sig->params [i], sig->params [i]);
+       
+       return sig;
+}
+
 static void
 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
 {
@@ -174,6 +221,11 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
                        _mono_type_get_assembly_name (type->data.klass, str);
                break;
        }
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR:
+               g_assert (type->data.generic_param->name);
+               g_string_append (str, type->data.generic_param->name);
+               break;
        default:
                klass = mono_class_from_mono_type (type);
                if (klass->nested_in) {
@@ -183,8 +235,7 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
                                g_string_append_c (str, '.');
                        else
                                g_string_append_c (str, '+');
-               }
-               if (*klass->name_space) {
+               } else if (*klass->name_space) {
                        g_string_append (str, klass->name_space);
                        g_string_append_c (str, '.');
                }
@@ -256,20 +307,27 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
 /**
  * mono_type_get_name:
  * @type: a type
+ * @format: the format for the return string.
  *
- * Returns: the string representation for type as required by System.Reflection.
- * The inverse of mono_reflection_parse_type ().
+ * 
+ * Returns: the string representation in a number of formats:
+ *
+ * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
+ * returned in the formatrequired by System.Reflection, this is the
+ * inverse of mono_reflection_parse_type ().
+ *
+ * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
+ * be used by the IL assembler.
+ *
+ * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
+ *
+ * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
  */
 char*
 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
 {
        GString* result;
 
-       if (format == MONO_TYPE_NAME_FORMAT_FULL_NAME &&
-           ((type->type == MONO_TYPE_VAR) || (type->type == MONO_TYPE_MVAR) ||
-            ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->inst->is_open)))
-               return NULL;
-
        result = g_string_new ("");
 
        mono_type_get_name_recurse (type, result, FALSE, format);
@@ -280,6 +338,19 @@ mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
        return g_string_free (result, FALSE);
 }
 
+/**
+ * mono_type_get_full_name:
+ * @class: a class
+ *
+ * Returns: the string representation for type as required by System.Reflection.
+ * The inverse of mono_reflection_parse_type ().
+ */
+char *
+mono_type_get_full_name (MonoClass *class)
+{
+       return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
+}
+
 char*
 mono_type_get_name (MonoType *type)
 {
@@ -357,7 +428,7 @@ inflate_generic_class (MonoGenericClass *ogclass, MonoGenericContext *context)
        igclass->klass = NULL;
 
        ngclass->context = g_new0 (MonoGenericContext, 1);
-       ngclass->context->container = context->container;
+       ngclass->context->container = ngclass->container_class->generic_container;
        ngclass->context->gclass = ngclass;
 
        mono_loader_lock ();
@@ -523,15 +594,29 @@ inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflat
        } else
                res->gmethod = inflate_with->gmethod;
 
+       if (res->gmethod) {
+               res->gmethod->container->parent = res->container;
+               res->container = res->gmethod->container;
+       }
+
        return res;
 }
 
+/**
+ * mono_class_inflate_generic_method:
+ *
+ * Instantiate method @method with the generic context @context.
+ */
 MonoMethod*
 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
 {
        MonoMethodInflated *result;
+       MonoGenericContainer *container = context ? context->container : NULL;
+       MonoMethodSignature *sig;
 
-       if (method->is_inflated || mono_method_signature_full (method, context)->is_inflated) {
+       /* The `method' has already been instantiated before -> we need to create a new context. */
+       sig = mono_method_signature_full (method, container);
+       if (method->is_inflated || sig->is_inflated) {
                MonoMethodInflated *imethod = (MonoMethodInflated *) method;
 
                context = inflate_generic_context (imethod->context, context);
@@ -540,18 +625,29 @@ mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *conte
 
        mono_stats.inflated_method_count++;
 
+       /* Just create a copy, but don't actually inflate the method for performance reasons. */
        result = g_new0 (MonoMethodInflated, 1);
-       result->nmethod = *(MonoMethodNormal*)method;
-       result->nmethod.method.is_inflated = 1;
+       if (sig->pinvoke)
+               result->method.pinvoke = *(MonoMethodPInvoke*)method;
+       else
+               result->method.normal = *(MonoMethodNormal*)method;
+       result->method.method.is_inflated = 1;
        result->context = context;
        result->declaring = method;
 
-       if (result->nmethod.method.klass->generic_class)
-               result->nmethod.method.klass = result->nmethod.method.klass->generic_class->container_class;
+       if (result->method.method.klass->generic_class)
+               result->method.method.klass = result->method.method.klass->generic_class->container_class;
 
        return (MonoMethod *) result;
 }
 
+/**
+ * mono_get_inflated_method:
+ *
+ * For performance reasons, mono_class_inflate_generic_method() does not actually instantiate the
+ * method, it just "prepares" it for that.  If you really need to fully instantiate the method
+ * (including its signature and header), call this method.
+ */
 MonoMethod *
 mono_get_inflated_method (MonoMethod *method)
 {
@@ -577,26 +673,82 @@ mono_get_inflated_method (MonoMethod *method)
 
        mh = mono_method_get_header (method);
        if (mh)
-               res->nmethod.header = inflate_generic_header (mh, imethod->context);
+               res->method.normal.header = inflate_generic_header (mh, imethod->context);
 
        dtype = mono_class_inflate_generic_type (&method->klass->byval_arg, imethod->context);
-       rklass = res->nmethod.method.klass = mono_class_from_mono_type (dtype);
+       rklass = res->method.method.klass = mono_class_from_mono_type (dtype);
 
-       res->nmethod.method.signature = mono_class_inflate_generic_signature (
+       res->method.method.signature = mono_class_inflate_generic_signature (
                method->klass->image, mono_method_signature (method), imethod->context);
 
        return (MonoMethod *) res;
 }
 
 /** 
- * class_compute_field_layout:
- * @m: pointer to the metadata.
+ * mono_class_find_enum_basetype:
+ * @class: The enum class
+ *
+ *   Determine the basetype of an enum by iterating through its fields. We do this
+ * in a separate function since it is cheaper than calling mono_class_setup_fields.
+ */
+static MonoType*
+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);
+
+       /*
+        * Fetch all the field information.
+        */
+       for (i = 0; i < top; i++){
+               const char *sig;
+               guint32 cols [MONO_FIELD_SIZE];
+               int idx = class->field.first + i;
+               MonoGenericContainer *container = NULL;
+               MonoType *ftype;
+
+               mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
+               sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
+               mono_metadata_decode_value (sig, &sig);
+               /* FIELD signature == 0x06 */
+               g_assert (*sig == 0x06);
+               if (class->generic_container)
+                       container = class->generic_container;
+               else if (class->generic_class) {
+                       MonoClass *gklass = class->generic_class->container_class;
+
+                       container = gklass->generic_container;
+                       g_assert (container);
+               }
+               ftype = mono_metadata_parse_type_full (
+                       m, (MonoGenericContext *) container, MONO_PARSE_FIELD,
+                       cols [MONO_FIELD_FLAGS], sig + 1, &sig);
+               if (class->generic_class) {
+                       ftype = mono_class_inflate_generic_type (
+                               ftype, class->generic_class->context);
+                       ftype->attrs = cols [MONO_FIELD_FLAGS];
+               }
+
+               if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC))
+                       return ftype;
+       }
+
+       return NULL;
+}
+
+/** 
+ * mono_class_setup_fields:
  * @class: The class to initialize
  *
  * Initializes the class->fields.
+ * Assumes the loader lock is held.
  */
 static void
-class_compute_field_layout (MonoClass *class)
+mono_class_setup_fields (MonoClass *class)
 {
        MonoImage *m = class->image; 
        const int top = class->field.count;
@@ -611,9 +763,15 @@ class_compute_field_layout (MonoClass *class)
        if (class->size_inited)
                return;
 
+       if (class->inited)
+               mono_class_init (class);
+
+       class->instance_size = 0;
+       class->class_size = 0;
+
        if (class->parent) {
                if (!class->parent->size_inited)
-                       class_compute_field_layout (class->parent);
+                       mono_class_setup_fields (class->parent);
                class->instance_size += class->parent->instance_size;
                class->min_align = class->parent->min_align;
                /* we use |= since it may have been set already */
@@ -648,7 +806,7 @@ class_compute_field_layout (MonoClass *class)
        /* Prevent infinite loops if the class references itself */
        class->size_inited = 1;
 
-       class->fields = g_new0 (MonoClassField, top);
+       class->fields = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClassField) * top);
 
        /*
         * Fetch all the field information.
@@ -741,6 +899,40 @@ class_compute_field_layout (MonoClass *class)
        mono_class_layout_fields (class);
 }
 
+/** 
+ * mono_class_setup_fields_locking:
+ * @class: The class to initialize
+ *
+ * Initializes the class->fields.
+ * Aquires the loader lock.
+ */
+static void
+mono_class_setup_fields_locking (MonoClass *class)
+{
+       mono_loader_lock ();
+       mono_class_setup_fields (class);
+       mono_loader_unlock ();
+}
+
+/*
+ * mono_class_has_references:
+ *
+ *   Returns whenever @klass->has_references is set, initializing it if needed.
+ * Aquires the loader lock.
+ */
+static gboolean
+mono_class_has_references (MonoClass *klass)
+{
+       if (klass->init_pending) {
+               /* Be conservative */
+               return TRUE;
+       } else {
+               mono_class_init (klass);
+
+               return klass->has_references;
+       }
+}
+
 /* useful until we keep track of gc-references in corlib etc. */
 #define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U || (t)->type == MONO_TYPE_I || (t)->type == MONO_TYPE_PTR)
 
@@ -777,6 +969,49 @@ mono_class_layout_fields (MonoClass *class)
                        gc_aware_layout = TRUE;
        }
 
+       /* Compute klass->has_references */
+       /* 
+        * Process non-static fields first, since static fields might recursively
+        * refer to the class itself.
+        */
+       for (i = 0; i < top; i++) {
+               MonoType *ftype;
+
+               field = &class->fields [i];
+
+               if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
+                       ftype = mono_type_get_underlying_type (field->type);
+                       if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+                               class->has_references = TRUE;
+               }
+       }
+
+       for (i = 0; i < top; i++) {
+               MonoType *ftype;
+
+               field = &class->fields [i];
+
+               if (!field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
+                       ftype = mono_type_get_underlying_type (field->type);
+                       if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+                               class->has_static_refs = TRUE;
+               }
+       }
+
+       for (i = 0; i < top; i++) {
+               MonoType *ftype;
+
+               field = &class->fields [i];
+
+               ftype = mono_type_get_underlying_type (field->type);
+               if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
+                       if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+                               class->has_static_refs = TRUE;
+                       else
+                               class->has_references = TRUE;
+               }
+       }
+
        /*
         * Compute field layout and total size (not considering static fields)
         */
@@ -801,6 +1036,7 @@ mono_class_layout_fields (MonoClass *class)
                for (pass = 0; pass < passes; ++pass) {
                        for (i = 0; i < top; i++){
                                int size, align;
+
                                field = &class->fields [i];
 
                                if (mono_field_is_deleted (field))
@@ -840,10 +1076,6 @@ mono_class_layout_fields (MonoClass *class)
                                field->offset += align - 1;
                                field->offset &= ~(align - 1);
                                real_size = field->offset + size;
-                               if (MONO_TYPE_IS_REFERENCE (field->type) || IS_GC_REFERENCE (field->type))
-                                       class->has_references = TRUE;
-                               else if (field->type->type == MONO_TYPE_VALUETYPE && field->type->data.klass->has_references)
-                                       class->has_references = TRUE;
                        }
 
                        class->instance_size = MAX (real_size, class->instance_size);
@@ -858,6 +1090,7 @@ mono_class_layout_fields (MonoClass *class)
                real_size = 0;
                for (i = 0; i < top; i++) {
                        int size, align;
+
                        field = &class->fields [i];
 
                        /*
@@ -870,10 +1103,6 @@ mono_class_layout_fields (MonoClass *class)
                        if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
                                continue;
 
-                       if (MONO_TYPE_IS_REFERENCE (field->type) || IS_GC_REFERENCE (field->type))
-                               class->has_references = TRUE;
-                       else if (field->type->type == MONO_TYPE_VALUETYPE && field->type->data.klass->has_references)
-                               class->has_references = TRUE;
                        size = mono_type_size (field->type, &align);
                        
                        /*
@@ -900,6 +1129,7 @@ mono_class_layout_fields (MonoClass *class)
         */
        for (i = 0; i < top; i++){
                int size, align;
+
                field = &class->fields [i];
                        
                if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
@@ -907,10 +1137,6 @@ mono_class_layout_fields (MonoClass *class)
                if (mono_field_is_deleted (field))
                        continue;
 
-               if (MONO_TYPE_IS_REFERENCE (field->type) || IS_GC_REFERENCE (field->type))
-                       class->has_static_refs = TRUE;
-               else if (field->type->type == MONO_TYPE_VALUETYPE && field->type->data.klass->has_references)
-                       class->has_static_refs = TRUE;
                size = mono_type_size (field->type, &align);
                field->offset = class->class_size;
                field->offset += align - 1;
@@ -932,7 +1158,7 @@ mono_class_setup_methods (MonoClass *class)
        int i;
        MonoMethod **methods;
 
-       if (class->methods || class->generic_class)
+       if (class->methods)
                return;
 
        mono_loader_lock ();
@@ -944,11 +1170,10 @@ mono_class_setup_methods (MonoClass *class)
 
        //printf ("INIT: %s.%s\n", class->name_space, class->name);
 
-       if (!class->generic_class && !class->methods) {
-               methods = g_new (MonoMethod*, class->method.count);
+       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);
+                       methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
                }
        }
 
@@ -956,6 +1181,7 @@ mono_class_setup_methods (MonoClass *class)
                for (i = 0; i < class->method.count; ++i)
                        methods [i]->slot = i;
 
+       /* Leave this assignment as the last op in this function */
        class->methods = methods;
 
        mono_loader_unlock ();
@@ -970,6 +1196,7 @@ mono_class_setup_properties (MonoClass *class)
        MonoTableInfo *pt = &class->image->tables [MONO_TABLE_PROPERTY];
        MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
        MonoProperty *properties;
+       guint32 last;
 
        if (class->properties)
                return;
@@ -981,14 +1208,14 @@ mono_class_setup_properties (MonoClass *class)
                return;
        }
 
-       class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->property.last);
-       class->property.count = class->property.last - class->property.first;
+       class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
+       class->property.count = last - class->property.first;
 
        if (class->property.count)
                mono_class_setup_methods (class);
 
-       properties = g_new0 (MonoProperty, class->property.count);
-       for (i = class->property.first; i < class->property.last; ++i) {
+       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);
                properties [i - class->property.first].parent = class;
                properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
@@ -1010,6 +1237,7 @@ mono_class_setup_properties (MonoClass *class)
                }
        }
 
+       /* Leave this assignment as the last op in the function */
        class->properties = properties;
 
        mono_loader_unlock ();
@@ -1022,19 +1250,27 @@ mono_class_setup_events (MonoClass *class)
        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;
 
        if (class->events)
                return;
 
-       class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->event.last);
-       class->event.count = class->event.last - class->event.first;
+       mono_loader_lock ();
+
+       if (class->events) {
+               mono_loader_unlock ();
+               return;
+       }
+       class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
+       class->event.count = last - class->event.first;
 
        if (class->event.count)
                mono_class_setup_methods (class);
 
-       class->events = g_new0 (MonoEvent, class->event.count);
-       for (i = class->event.first; i < class->event.last; ++i) {
-               MonoEvent *event = &class->events [i - class->event.first];
+       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);
                event->parent = class;
@@ -1072,6 +1308,10 @@ mono_class_setup_events (MonoClass *class)
                        }
                }
        }
+       /* Leave this assignment as the last op in the function */
+       class->events = events;
+
+       mono_loader_unlock ();
 }
 
 static guint
@@ -1082,6 +1322,7 @@ mono_get_unique_iid (MonoClass *class)
 
        char *str;
        gpointer value;
+       int generic_id;
        
        g_assert (MONO_CLASS_IS_INTERFACE (class));
 
@@ -1090,7 +1331,14 @@ mono_get_unique_iid (MonoClass *class)
        if (!iid_hash)
                iid_hash = g_hash_table_new (g_str_hash, g_str_equal);
 
-       str = g_strdup_printf ("%s|%s.%s\n", class->image->name, class->name_space, class->name);
+       if (class->generic_class && !class->generic_class->inst->is_open) {
+               generic_id = class->generic_class->inst->id;
+               g_assert (generic_id != 0);
+       } else
+               generic_id = 0;
+
+       str = g_strdup_printf ("%s|%s.%s|%d", class->image->name, class->name_space, class->name,
+                              generic_id);
 
        if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
                mono_loader_unlock ();
@@ -1281,11 +1529,42 @@ setup_interface_offsets (MonoClass *class, int cur_slot)
        return cur_slot;
 }
 
+static void
+setup_generic_vtable (MonoClass *class)
+{
+       MonoClass *gklass;
+       int i;
+
+       gklass = class->generic_class->container_class;
+
+       mono_class_init (gklass);
+       class->vtable_size = gklass->vtable_size;
+
+       class->vtable = g_new0 (MonoMethod*, class->vtable_size);
+       memcpy (class->vtable, gklass->vtable,  sizeof (MonoMethod*) * class->vtable_size);
+
+       for (i = 0; i < class->vtable_size; i++) {
+               MonoMethod *m = class->vtable [i];
+
+               if (!m)
+                       continue;
+
+               m = mono_class_inflate_generic_method (m, class->generic_class->context);
+               class->vtable [i] = m;
+       }
+
+       class->max_interface_id = gklass->max_interface_id;
+       class->interface_offsets = g_new0 (gint, gklass->max_interface_id + 1);
+       memcpy (class->interface_offsets, gklass->interface_offsets,
+               sizeof (gint) * (gklass->max_interface_id + 1));
+}
+
 void
 mono_class_setup_vtable (MonoClass *class)
 {
        MonoMethod **overrides;
        MonoGenericContext *context;
+       guint32 type_token;
        int onum = 0;
 
        if (class->vtable)
@@ -1303,49 +1582,31 @@ mono_class_setup_vtable (MonoClass *class)
                return;
        }
 
-       if (class->generic_class)
+       if (class->generic_class) {
+               if (class->generic_class->inst->is_open) {
+                       setup_generic_vtable (class);
+                       mono_loader_unlock ();
+                       return;
+               }
+
                context = class->generic_class->context;
-       else
+               type_token = class->generic_class->container_class->type_token;
+       } else {
                context = (MonoGenericContext *) class->generic_container;              
+               type_token = class->type_token;
+       }
+
+       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);
 
-       overrides = mono_class_get_overrides_full (
-               class->image, class->type_token, &onum, context);
        mono_class_setup_vtable_general (class, overrides, onum);
        g_free (overrides);
 
        mono_loader_unlock ();
 }
 
-static void
-setup_generic_vtable (MonoClass *class, MonoMethod **overrides, int onum)
-{
-       MonoClass *gklass;
-       int i;
-
-       gklass = class->generic_class->container_class;
-
-       mono_class_init (gklass);
-       class->vtable_size = gklass->vtable_size;
-
-       class->vtable = g_new0 (MonoMethod*, class->vtable_size);
-       memcpy (class->vtable, gklass->vtable,  sizeof (MonoMethod*) * class->vtable_size);
-
-       for (i = 0; i < class->vtable_size; i++) {
-               MonoMethod *m = class->vtable [i];
-
-               if (!m)
-                       continue;
-
-               m = mono_class_inflate_generic_method (m, class->generic_class->context);
-               class->vtable [i] = m;
-       }
-
-       class->max_interface_id = gklass->max_interface_id;
-       class->interface_offsets = g_new0 (gint, gklass->max_interface_id + 1);
-       memcpy (class->interface_offsets, gklass->interface_offsets,
-               sizeof (gint) * (gklass->max_interface_id + 1));
-}
-
 /*
  * LOCKING: this is supposed to be called with the loader lock held.
  */
@@ -1355,15 +1616,15 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
        MonoClass *k, *ic;
        MonoMethod **vtable;
        int i, max_vtsize = 0, max_iid, cur_slot = 0;
-       GPtrArray *ifaces;
+       GPtrArray *ifaces, *pifaces = NULL;
        GHashTable *override_map = NULL;
        gboolean security_enabled = mono_is_security_manager_active ();
 
        if (class->vtable)
                return;
 
-       if (class->generic_class) {
-               setup_generic_vtable (class, overrides, onum);
+       if (class->generic_class && class->generic_class->inst->is_open) {
+               setup_generic_vtable (class);
                return;
        }
 
@@ -1417,12 +1678,22 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                int nifaces = 0;
 
                ifaces = mono_class_get_implemented_interfaces (k);
-               if (ifaces)
+               if (ifaces) {
                        nifaces = ifaces->len;
+                       if (k->generic_class) {
+                               pifaces = mono_class_get_implemented_interfaces (
+                                       k->generic_class->container_class);
+                               g_assert (pifaces && (pifaces->len == nifaces));
+                       }
+               }
                for (i = 0; i < nifaces; i++) {
+                       MonoClass *pic = NULL;
                        int j, l, io;
 
                        ic = g_ptr_array_index (ifaces, i);
+                       if (pifaces)
+                               pic = g_ptr_array_index (pifaces, i);
+                       g_assert (ic->interface_id <= k->max_interface_id);
                        io = k->interface_offsets [ic->interface_id];
 
                        g_assert (io >= 0);
@@ -1506,8 +1777,8 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                if (vtable [io + l])
                                        continue;
 
-                               if (ic->generic_class) {
-                                       the_cname = mono_type_get_name_full (&ic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
+                               if (pic) {
+                                       the_cname = mono_type_get_name_full (&pic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
                                        cname = the_cname;
                                } else {
                                        the_cname = NULL;
@@ -1563,7 +1834,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                                MonoClass *parent = class->parent;
 
                                                if ((ic->interface_id <= parent->max_interface_id) && 
-                                                       (parent->interface_offsets [ic->interface_id]) &&
+                                                       (parent->interface_offsets [ic->interface_id] != -1) &&
                                                        parent->vtable)
                                                        vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
                                        }
@@ -1579,7 +1850,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                                g_free (msig);
                                                for (j = 0; j < class->method.count; ++j) {
                                                        MonoMethod *cm = class->methods [j];
-                                                       msig = mono_signature_get_desc (mono_method_signature (cm), FALSE);
+                                                       msig = mono_signature_get_desc (mono_method_signature (cm), TRUE);
                                                        
                                                        printf ("METHOD %s(%s)\n", cm->name, msig);
                                                        g_free (msig);
@@ -1656,7 +1927,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                if (cm->slot < 0)
                        cm->slot = cur_slot++;
 
-               if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT) && ! mono_method_signature (cm)->generic_param_count)
+               if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
                        vtable [cm->slot] = cm;
        }
 
@@ -1692,8 +1963,9 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                MonoClass *gklass = class->generic_class->container_class;
 
                mono_class_init (gklass);
-               class->vtable_size = gklass->vtable_size;
-       } else       
+
+               class->vtable_size = MAX (gklass->vtable_size, cur_slot);
+       } else
                class->vtable_size = cur_slot;
 
        class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size);
@@ -1762,6 +2034,7 @@ mono_class_init (MonoClass *class)
        static int finalize_slot = -1;
        static int ghc_slot = -1;
        MonoCachedClassInfo cached_info;
+       gboolean has_cached_info;
 
        g_assert (class);
 
@@ -1780,17 +2053,7 @@ mono_class_init (MonoClass *class)
        }
 
        if (class->init_pending) {
-               /*
-                * We might be called recursively from mono_class_from_typeref if
-                * one of our fields has a type which is a nested type of this class,
-                * and the compiler encodes it as a typeref, like older versions of
-                * MS ilasm do.
-                */
-               if (class->size_inited) {
-                       mono_loader_unlock ();
-                       return;
-               }
-
+               mono_loader_unlock ();
                /* this indicates a cyclic dependency */
                g_error ("pending init %s.%s\n", class->name_space, class->name);
        }
@@ -1860,7 +2123,9 @@ mono_class_init (MonoClass *class)
        if (class->parent && !class->parent->inited)
                mono_class_init (class->parent);
 
-       if (!class->generic_class) {
+       has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
+
+       if (!class->generic_class && (!has_cached_info || (has_cached_info && cached_info.has_nested_classes))) {
                i = mono_metadata_nesting_typedef (class->image, class->type_token, 1);
                while (i) {
                        MonoClass* nclass;
@@ -1876,8 +2141,18 @@ mono_class_init (MonoClass *class)
        /*
         * Computes the size used by the fields, and their locations
         */
-       if (!class->size_inited)
-               class_compute_field_layout (class);
+       if (has_cached_info) {
+               class->instance_size = cached_info.instance_size;
+               class->class_size = cached_info.class_size;
+               class->packing_size = cached_info.packing_size;
+               class->min_align = cached_info.min_align;
+               class->blittable = cached_info.blittable;
+               class->has_references = cached_info.has_references;
+               class->has_static_refs = cached_info.has_static_refs;
+       }
+       else
+               if (!class->size_inited)
+                       mono_class_setup_fields (class);
 
        /* initialize method pointers */
        if (class->rank) {
@@ -1959,7 +2234,7 @@ mono_class_init (MonoClass *class)
         * If possible, avoid the creation of the generic vtable by requesting
         * cached info from the runtime.
         */
-       if (mono_class_get_cached_class_info (class, &cached_info)) {
+       if (has_cached_info) {
                guint32 cur_slot = 0;
 
                class->vtable_size = cached_info.vtable_size;
@@ -2242,28 +2517,6 @@ mono_class_setup_supertypes (MonoClass *class)
        }
 }      
 
-/*
- * If we inherit a type parameter from an outer class, set its owner to that class.
- */
-static int
-set_generic_param_owner (MonoGenericContainer *container, MonoClass *klass, int pos)
-{
-       MonoGenericContainer *gc;
-       int i;
-
-       if (klass->nested_in)
-               pos = set_generic_param_owner (container, klass->nested_in, pos);
-
-       if (!klass->generic_container)
-               return pos;
-
-       gc = klass->generic_container;
-       for (i = pos; i < gc->type_argc; i++)
-               container->type_params [i].owner = gc;
-
-       return pos + gc->type_argc;
-}
-
 static MonoGenericInst *
 get_shared_inst (MonoGenericContainer *container)
 {
@@ -2288,6 +2541,9 @@ get_shared_inst (MonoGenericContainer *container)
        return mono_metadata_lookup_generic_inst (nginst);
 }
 
+/*
+ * In preparation for implementing shared code.
+ */
 MonoGenericClass *
 mono_get_shared_generic_class (MonoGenericContainer *container, gboolean is_dynamic)
 {
@@ -2340,6 +2596,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        const char *name, *nspace;
        guint icount = 0; 
        MonoClass **interfaces;
+       guint32 field_last, method_last;
 
        mono_loader_lock ();
 
@@ -2366,6 +2623,9 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 
        g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
 
+       /*
+        * Check whether we're a generic type definition.
+        */
        class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
        if (class->generic_container) {
                class->generic_container->klass = class;
@@ -2374,18 +2634,21 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                context->gclass = mono_get_shared_generic_class (context->container, FALSE);
        }
 
-       if (cols [MONO_TYPEDEF_EXTENDS])
+       if (cols [MONO_TYPEDEF_EXTENDS]) {
                parent = mono_class_get_full (
                        image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
+       }
 
        mono_class_setup_parent (class, parent);
 
        mono_class_setup_mono_type (class);
 
-       interfaces = mono_metadata_interfaces_from_typedef_full (image, type_token, &icount, context);
+       if (!class->enumtype) {
+               mono_metadata_interfaces_from_typedef_full (image, type_token, &interfaces, &icount, context);
 
-       class->interfaces = interfaces;
-       class->interface_count = icount;
+               class->interfaces = interfaces;
+               class->interface_count = icount;
+       }
 
        if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
                class->unicode = 1;
@@ -2406,21 +2669,21 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 
        if (tt->rows > tidx){           
                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;
+               field_last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
+               method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
        } else {
-               class->field.last  = image->tables [MONO_TABLE_FIELD].rows;
-               class->method.last = image->tables [MONO_TABLE_METHOD].rows;
+               field_last  = image->tables [MONO_TABLE_FIELD].rows;
+               method_last = image->tables [MONO_TABLE_METHOD].rows;
        }
 
        if (cols [MONO_TYPEDEF_FIELD_LIST] && 
            cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
-               class->field.count = class->field.last - class->field.first;
+               class->field.count = field_last - class->field.first;
        else
                class->field.count = 0;
 
        if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
-               class->method.count = class->method.last - class->method.first;
+               class->method.count = method_last - class->method.first;
        else
                class->method.count = 0;
 
@@ -2430,20 +2693,49 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                g_assert (class->field.count == 0);
        }
 
-       if (class->enumtype)
-               class_compute_field_layout (class);
+       if (class->enumtype) {
+               class->enum_basetype = mono_class_find_enum_basetype (class);
+               class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
+       }
+
+       /*
+        * If we're a generic type definition, load the constraints.
+        * We must do this after the class has been constructed to make certain recursive scenarios
+        * work.
+        */
+       if (class->generic_container)
+               mono_metadata_load_generic_param_constraints (
+                       image, type_token, class->generic_container);
 
        if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
                class->nested_in = mono_class_create_from_typedef (image, type_token);
 
-       if (class->nested_in && class->generic_container)
-               set_generic_param_owner (class->generic_container, class->nested_in, 0);
-
        mono_loader_unlock ();
 
        return class;
 }
 
+/** is klass Nullable<T>? */
+gboolean
+mono_class_is_nullable (MonoClass *klass)
+{
+       return klass->generic_class != NULL &&
+               klass->generic_class->container_class == mono_defaults.generic_nullable_class;
+}
+
+
+/** if klass is T? return T */
+MonoClass*
+mono_class_get_nullable_param (MonoClass *klass)
+{
+       g_assert (mono_class_is_nullable (klass));
+       return mono_class_from_mono_type (klass->generic_class->inst->type_argv [0]);
+}
+
+/*
+ * Create the `MonoClass' for an instantiation of a generic type.
+ * We only do this if we actually need it.
+ */
 static void
 mono_class_create_generic (MonoInflatedGenericClass *gclass)
 {
@@ -2475,6 +2767,9 @@ mono_class_create_generic (MonoInflatedGenericClass *gclass)
 
        klass->cast_class = klass->element_class = klass;
 
+       if (mono_class_is_nullable (klass))
+               klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
+
        if (gclass->generic_class.is_dynamic) {
                klass->instance_size = gklass->instance_size;
                klass->class_size = gklass->class_size;
@@ -2520,6 +2815,9 @@ mono_class_create_generic (MonoInflatedGenericClass *gclass)
 
        if (klass->parent)
                mono_class_setup_parent (klass, klass->parent);
+
+       if (MONO_CLASS_IS_INTERFACE (klass))
+               setup_interface_offsets (klass, 0);
 }
 
 MonoClass *
@@ -2579,8 +2877,6 @@ my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar)
        if (param->pklass)
                return param->pklass;
 
-       g_assert (param->owner);
-
        klass = g_new0 (MonoClass, 1);
 
        if (param->name)
@@ -2773,7 +3069,7 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec,
 
        switch (type->type) {
        case MONO_TYPE_ARRAY:
-               class = mono_array_class_get (type->data.array->eklass, type->data.array->rank);
+               class = mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
                break;
        case MONO_TYPE_SZARRAY:
                class = mono_array_class_get (type->data.klass, 1);
@@ -2843,7 +3139,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
        }
 
        /* for the building corlib use System.Array from it */
-       if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "mscorlib") == 0) {
+       if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
                parent = mono_class_from_name (image, "System", "Array");
                corlib_type = TRUE;
        } else if (mono_defaults.generic_array_class) {
@@ -2888,7 +3184,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
        if (eclass->generic_class)
                mono_class_init (eclass);
        if (!eclass->size_inited)
-               class_compute_field_layout (eclass);
+               mono_class_setup_fields (eclass);
        class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
 
        class->rank = rank;
@@ -2917,6 +3213,8 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
                class->inited = 1;
        }
 
+       class->generic_container = eclass->generic_container;
+
        list = g_slist_append (rootlist, class);
        g_hash_table_insert (image->array_cache, eclass, list);
 
@@ -3019,16 +3317,17 @@ mono_class_data_size (MonoClass *klass)
 static MonoClassField *
 mono_class_get_field_idx (MonoClass *class, int idx)
 {
-       if (class->field.count){
-               if ((idx >= class->field.first) && (idx < class->field.last)){
-                       return &class->fields [idx - class->field.first];
+       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];
+                       }
                }
+               class = class->parent;
        }
-
-       if (!class->parent)
-               return NULL;
-       
-       return mono_class_get_field_idx (class->parent, idx);
+       return NULL;
 }
 
 /**
@@ -3050,11 +3349,21 @@ mono_class_get_field (MonoClass *class, guint32 field_token)
        return mono_class_get_field_idx (class, idx - 1);
 }
 
+/**
+ * mono_class_get_field_from_name:
+ * @klass: the class to lookup the field.
+ * @name: the field name
+ *
+ * Search the class @klass and it's parents for a field with the name @name.
+ * 
+ * Returns: the MonoClassField pointer of the named field or NULL
+ */
 MonoClassField *
 mono_class_get_field_from_name (MonoClass *klass, const char *name)
 {
        int i;
 
+       mono_class_setup_fields_locking (klass);
        while (klass) {
                for (i = 0; i < klass->field.count; ++i) {
                        if (strcmp (name, klass->fields [i].name) == 0)
@@ -3065,12 +3374,22 @@ mono_class_get_field_from_name (MonoClass *klass, const char *name)
        return NULL;
 }
 
+/**
+ * mono_class_get_field_token:
+ * @field: the field we need the token of
+ *
+ * Get the token of a field. Note that the tokesn is only valid for the image
+ * the field was loaded from. Don't use this function for fields in dynamic types.
+ * 
+ * Returns: the token representing the field in the image it was loaded from.
+ */
 guint32
 mono_class_get_field_token (MonoClassField *field)
 {
        MonoClass *klass = field->parent;
        int i;
 
+       mono_class_setup_fields_locking (klass);
        while (klass) {
                for (i = 0; i < klass->field.count; ++i) {
                        if (&klass->fields [i] == field)
@@ -3144,7 +3463,7 @@ mono_class_get_property_token (MonoProperty *prop)
 }
 
 char *
-mono_class_name_from_token (MonoImage *image, guint32 type_token, MonoGenericContext *context)
+mono_class_name_from_token (MonoImage *image, guint32 type_token)
 {
        const char *name, *nspace;
        if (image->dynamic)
@@ -3187,6 +3506,53 @@ mono_class_name_from_token (MonoImage *image, guint32 type_token, MonoGenericCon
        return NULL;
 }
 
+static char *
+mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
+{
+       if (image->dynamic)
+               return g_strdup_printf ("DynamicAssembly %s", image->name);
+       
+       switch (type_token & 0xff000000){
+       case MONO_TOKEN_TYPE_DEF:
+               return mono_stringify_assembly_name (&image->assembly->aname);
+               break;
+       case MONO_TOKEN_TYPE_REF: {
+               MonoAssemblyName aname;
+               guint32 cols [MONO_TYPEREF_SIZE];
+               MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
+               guint32 idx;
+       
+               mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
+
+               idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
+               switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
+               case MONO_RESOLTION_SCOPE_MODULE:
+                       /* FIXME: */
+                       return g_strdup ("");
+               case MONO_RESOLTION_SCOPE_MODULEREF:
+                       /* FIXME: */
+                       return g_strdup ("");
+               case MONO_RESOLTION_SCOPE_TYPEREF:
+                       /* FIXME: */
+                       return g_strdup ("");
+               case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
+                       mono_assembly_get_assemblyref (image, idx - 1, &aname);
+                       return mono_stringify_assembly_name (&aname);
+               default:
+                       g_assert_not_reached ();
+               }
+               break;
+       }
+       case MONO_TOKEN_TYPE_SPEC:
+               /* FIXME: */
+               return g_strdup ("");
+       default:
+               g_assert_not_reached ();
+       }
+
+       return NULL;
+}
+
 /**
  * mono_class_get:
  * @image: the image where the class resides
@@ -3219,9 +3585,9 @@ _mono_class_get (MonoImage *image, guint32 type_token, MonoGenericContext *conte
        }
 
        if (!class){
-               char *name = mono_class_name_from_token (image, type_token, context);
-               g_warning ("The class %s could not be loaded, used in %s (token 0x%08x)", name, image->name, type_token);
-               g_free (name);
+               char *name = mono_class_name_from_token (image, type_token);
+               char *assembly = mono_assembly_name_from_token (image, type_token);
+               mono_loader_set_error_type_load (name, assembly);
        }
 
        return class;
@@ -3261,6 +3627,21 @@ mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *c
        return mono_class_from_mono_type (inflated);
 }
 
+typedef struct {
+       gconstpointer key;
+       gpointer value;
+} FindUserData;
+
+static void
+find_nocase (gpointer key, gpointer value, gpointer user_data)
+{
+       char *name = (char*)key;
+       FindUserData *data = (FindUserData*)user_data;
+
+       if (!data->value && (g_strcasecmp (name, (char*)data->key) == 0))
+               data->value = value;
+}
+
 /**
  * mono_class_from_name_case:
  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
@@ -3286,6 +3667,37 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char
        const char *nspace;
        guint32 i, visib;
 
+       if (image->dynamic) {
+               guint32 token = 0;
+               FindUserData user_data;
+
+               mono_loader_lock ();
+
+               user_data.key = name_space;
+               user_data.value = NULL;
+               g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
+
+               if (user_data.value) {
+                       GHashTable *nspace_table = (GHashTable*)user_data.value;
+
+                       user_data.key = name;
+                       user_data.value = NULL;
+
+                       g_hash_table_foreach (nspace_table, find_nocase, &user_data);
+                       
+                       if (user_data.value)
+                               token = GPOINTER_TO_UINT (user_data.value);
+               }
+
+               mono_loader_unlock ();
+               
+               if (token)
+                       return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
+               else
+                       return NULL;
+
+       }
+
        /* add a cache if needed */
        for (i = 1; i <= t->rows; ++i) {
                mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
@@ -3324,7 +3736,7 @@ return_nested_in (MonoClass *class, char *nested) {
 
 
 /**
- * mono_class_from_name_case:
+ * mono_class_from_name:
  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
  * @name_space: the type namespace
  * @name: the type short name.
@@ -3456,11 +3868,6 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
        if (!oklass->inited)
                mono_class_init (oklass);
 
-       if (klass->generic_class)
-               klass = klass->generic_class->container_class;
-       if (oklass->generic_class)
-               oklass = oklass->generic_class->container_class;
-
        if (MONO_CLASS_IS_INTERFACE (klass)) {
                if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR))
                        return FALSE;
@@ -3509,19 +3916,7 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
                if (klass == mono_defaults.object_class)
                        return TRUE;
 
-       /*
-        * Custom version of mono_class_has_parent (oklass, klass)
-        */
-       if (oklass->idepth >= klass->idepth) {
-               MonoClass *parent = oklass->supertypes [klass->idepth - 1];
-
-               if (parent->generic_class)
-                       parent = parent->generic_class->container_class;
-
-               return klass == parent;
-       }
-
-       return FALSE;
+       return mono_class_has_parent (oklass, klass);
 }      
 
 /*
@@ -3691,6 +4086,8 @@ mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
                if (handle_class)
                        *handle_class = mono_defaults.typehandle_class;
                class = mono_class_get_full (image, token, context);
+               if (!class)
+                       return NULL;
                mono_class_init (class);
                /* We return a MonoType* as handle */
                return &class->byval_arg;
@@ -3700,16 +4097,20 @@ mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
                if (handle_class)
                        *handle_class = mono_defaults.typehandle_class;
                class = mono_class_create_from_typespec (image, token, context);
+               if (!class)
+                       return NULL;
                mono_class_init (class);
                return &class->byval_arg;
        }
        case MONO_TOKEN_FIELD_DEF: {
                MonoClass *class;
                guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
-               class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
-               mono_class_init (class);
                if (handle_class)
                        *handle_class = mono_defaults.fieldhandle_class;
+               class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
+               if (!class)
+                       return NULL;
+               mono_class_init (class);
                return mono_class_get_field (class, token);
        }
        case MONO_TOKEN_METHOD_DEF: {
@@ -4016,8 +4417,7 @@ mono_class_get_fields (MonoClass* klass, gpointer *iter)
        MonoClassField* field;
        if (!iter)
                return NULL;
-       if (!klass->inited)
-               mono_class_init (klass);
+       mono_class_setup_fields_locking (klass);
        if (!*iter) {
                /* start from the first */
                if (klass->field.count) {
@@ -4521,7 +4921,7 @@ mono_class_get_exception_for_failure (MonoClass *klass)
                MonoDomain *domain = mono_domain_get ();
                MonoSecurityManager* secman = mono_security_manager_get_methods ();
                MonoMethod *method = klass->exception_data;
-               guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_CLASS : MONO_METADATA_INHERITANCEDEMAND_METHOD;
+               guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
                MonoObject *exc = NULL;
                gpointer args [4];