Tue Sep 23 15:24:03 CEST 2008 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / class.c
index b637c33d8caccfa739547de5ccd5709a2bb07140..bcd4a7a5ae3840b2df50e9b152723e856784688d 100644 (file)
@@ -112,7 +112,7 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
                MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
                GList *tmp;
 
-               if (enclosing->inited) {
+               if (enclosing->nested_classes_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;
@@ -160,29 +160,48 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
        return mono_class_from_name (image->references [idx - 1]->image, nspace, name);
 }
 
+
+static void *
+mono_mempool_dup (MonoMemPool *mp, void *data, guint size)
+{
+       void *res = mono_mempool_alloc (mp, size);
+       memcpy (res, data, size);
+       return res;
+}
+       
 /* Copy everything mono_metadata_free_array free. */
 MonoArrayType *
-mono_dup_array_type (MonoArrayType *a)
+mono_dup_array_type (MonoMemPool *mp, 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));
+       if (mp) {
+               mono_loader_lock ();
+               a = mono_mempool_dup (mp, a, sizeof (MonoArrayType));
+               if (a->sizes)
+                       a->sizes = mono_mempool_dup (mp, a->sizes, a->numsizes * sizeof (int));
+               if (a->lobounds)
+                       a->lobounds = mono_mempool_dup (mp, a->lobounds, a->numlobounds * sizeof (int));
+               mono_loader_unlock ();          
+       } else {
+               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)
+mono_metadata_signature_deep_dup (MonoMemPool *mp, MonoMethodSignature *sig)
 {
        int i;
        
-       sig = mono_metadata_signature_dup (sig);
+       sig = mono_metadata_signature_dup_full (mp, sig);
        
-       sig->ret = mono_metadata_type_dup (NULL, sig->ret);
+       sig->ret = mono_metadata_type_dup (mp, sig->ret);
        for (i = 0; i < sig->param_count; ++i)
-               sig->params [i] = mono_metadata_type_dup (NULL, sig->params [i]);
+               sig->params [i] = mono_metadata_type_dup (mp, sig->params [i]);
        
        return sig;
 }
@@ -460,7 +479,7 @@ mono_class_is_open_constructed_type (MonoType *t)
 }
 
 static MonoType*
-inflate_generic_type (MonoType *type, MonoGenericContext *context)
+inflate_generic_type (MonoMemPool *mempool, MonoType *type, MonoGenericContext *context)
 {
        switch (type->type) {
        case MONO_TYPE_MVAR: {
@@ -477,7 +496,7 @@ inflate_generic_type (MonoType *type, MonoGenericContext *context)
                 * while the VAR/MVAR duplicates a type from the context.  So, we need to ensure that the
                 * ->byref and ->attrs from @type are propagated to the returned type.
                 */
-               nt = mono_metadata_type_dup (NULL, inst->type_argv [num]);
+               nt = mono_metadata_type_dup (mempool, inst->type_argv [num]);
                nt->byref = type->byref;
                nt->attrs = type->attrs;
                return nt;
@@ -490,27 +509,27 @@ inflate_generic_type (MonoType *type, MonoGenericContext *context)
                        return NULL;
                if (num >= inst->type_argc)
                        g_error ("VAR %d (%s) cannot be expanded in this context with %d instantiations", num, type->data.generic_param->name, inst->type_argc);
-               nt = mono_metadata_type_dup (NULL, inst->type_argv [num]);
+               nt = mono_metadata_type_dup (mempool, inst->type_argv [num]);
                nt->byref = type->byref;
                nt->attrs = type->attrs;
                return nt;
        }
        case MONO_TYPE_SZARRAY: {
                MonoClass *eclass = type->data.klass;
-               MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
+               MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context);
                if (!inflated)
                        return NULL;
-               nt = mono_metadata_type_dup (NULL, type);
+               nt = mono_metadata_type_dup (mempool, type);
                nt->data.klass = mono_class_from_mono_type (inflated);
                mono_metadata_free_type (inflated);
                return nt;
        }
        case MONO_TYPE_ARRAY: {
                MonoClass *eclass = type->data.array->eklass;
-               MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
+               MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context);
                if (!inflated)
                        return NULL;
-               nt = mono_metadata_type_dup (NULL, type);
+               nt = mono_metadata_type_dup (mempool, type);
                nt->data.array = g_memdup (nt->data.array, sizeof (MonoArrayType));
                nt->data.array->eklass = mono_class_from_mono_type (inflated);
                mono_metadata_free_type (inflated);
@@ -530,7 +549,7 @@ inflate_generic_type (MonoType *type, MonoGenericContext *context)
                if (gclass == type->data.generic_class)
                        return NULL;
 
-               nt = mono_metadata_type_dup (NULL, type);
+               nt = mono_metadata_type_dup (mempool, type);
                nt->data.generic_class = gclass;
                return nt;
        }
@@ -552,7 +571,7 @@ inflate_generic_type (MonoType *type, MonoGenericContext *context)
 
                gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic);
 
-               nt = mono_metadata_type_dup (NULL, type);
+               nt = mono_metadata_type_dup (mempool, type);
                nt->type = MONO_TYPE_GENERICINST;
                nt->data.generic_class = gclass;
                return nt;
@@ -576,31 +595,48 @@ mono_class_get_context (MonoClass *class)
 }
 
 /*
- * mono_class_inflate_generic_type:
+ * mono_class_inflate_generic_type_with_mempool:
+ * @mempool: a mempool
  * @type: a type
  * @context: a generics context
  *
- * If @type is a generic type and @context is not NULL, instantiate it using the 
- * generics context @context.
- *
- * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
- * on the heap and is owned by the caller.
+ * The same as mono_class_inflate_generic_type, but allocates the MonoType
+ * from mempool if it is non-NULL.  If it is NULL, the MonoType is
+ * allocated on the heap and is owned by the caller.
  */
 MonoType*
-mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
+mono_class_inflate_generic_type_with_mempool (MonoMemPool *mempool, MonoType *type, MonoGenericContext *context)
 {
        MonoType *inflated = NULL; 
 
        if (context)
-               inflated = inflate_generic_type (type, context);
+               inflated = inflate_generic_type (mempool, type, context);
 
        if (!inflated)
-               return mono_metadata_type_dup (NULL, type);
+               return mono_metadata_type_dup (mempool, type);
 
        mono_stats.inflated_type_count++;
        return inflated;
 }
 
+/*
+ * mono_class_inflate_generic_type:
+ * @type: a type
+ * @context: a generics context
+ *
+ * If @type is a generic type and @context is not NULL, instantiate it using the 
+ * generics context @context.
+ *
+ * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
+ * on the heap and is owned by the caller.
+ */
+MonoType*
+mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
+{
+       return mono_class_inflate_generic_type_with_mempool (NULL, type, context);
+}
+
+
 static MonoGenericContext
 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with)
 {
@@ -710,6 +746,14 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin
        if (!context->method_inst && method->is_generic)
                iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
 
+       if (!context->class_inst) {
+               g_assert (!iresult->declaring->klass->generic_class);
+               if (iresult->declaring->klass->generic_container)
+                       iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
+               else if (iresult->declaring->klass->generic_class)
+                       iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
+       }
+
        mono_loader_lock ();
        cached = mono_method_inflated_lookup (iresult, FALSE);
        if (cached) {
@@ -752,7 +796,7 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin
                result->klass = klass_hint;
 
        if (!result->klass) {
-               MonoType *inflated = inflate_generic_type (&method->klass->byval_arg, context);
+               MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context);
                result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
                if (inflated)
                        mono_metadata_free_type (inflated);
@@ -867,6 +911,7 @@ mono_class_find_enum_basetype (MonoClass *class)
                if (!ftype)
                        return NULL;
                if (class->generic_class) {
+                       //FIXME do we leak here?
                        ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
                        ftype->attrs = cols [MONO_FIELD_FLAGS];
                }
@@ -962,7 +1007,7 @@ mono_class_setup_fields (MonoClass *class)
        /* Prevent infinite loops if the class references itself */
        class->size_inited = 1;
 
-       class->fields = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClassField) * top);
+       class->fields = mono_image_alloc0 (class->image, sizeof (MonoClassField) * top);
 
        if (class->generic_container) {
                container = class->generic_container;
@@ -990,7 +1035,8 @@ mono_class_setup_fields (MonoClass *class)
                        ifield->generic_type = gfield->type;
                        field->name = gfield->name;
                        field->generic_info = ifield;
-                       field->type = mono_class_inflate_generic_type (gfield->type, mono_class_get_context (class));
+                       /*This memory must come from the image mempool as we don't have a chance to free it.*/
+                       field->type = mono_class_inflate_generic_type_with_mempool (class->image->mempool, gfield->type, mono_class_get_context (class));
                        field->type->attrs = gfield->type->attrs;
                        if (mono_field_is_deleted (field))
                                continue;
@@ -1039,6 +1085,8 @@ mono_class_setup_fields (MonoClass *class)
                                blittable = FALSE;
                        } else {
                                MonoClass *field_class = mono_class_from_mono_type (field->type);
+                               if (field_class)
+                                       mono_class_setup_fields (field_class);
                                if (!field_class || !field_class->blittable)
                                        blittable = FALSE;
                        }
@@ -1386,7 +1434,7 @@ create_array_method (MonoClass *class, const char *name, MonoMethodSignature *si
 {
        MonoMethod *method;
 
-       method = (MonoMethod *) mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethodPInvoke));
+       method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
        method->klass = class;
        method->flags = METHOD_ATTRIBUTE_PUBLIC;
        method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
@@ -1456,7 +1504,7 @@ mono_class_setup_methods (MonoClass *class)
                        class->method.count += class->interface_count * count_generic;
                }
 
-               methods = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethod*) * class->method.count);
+               methods = mono_image_alloc0 (class->image, sizeof (MonoMethod*) * class->method.count);
 
                sig = mono_metadata_signature_alloc (class->image, class->rank);
                sig->ret = &mono_defaults.void_class->byval_arg;
@@ -1510,7 +1558,7 @@ mono_class_setup_methods (MonoClass *class)
                for (i = 0; i < class->interface_count; i++)
                        setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
        } else {
-               methods = mono_mempool_alloc (class->image->mempool, sizeof (MonoMethod*) * class->method.count);
+               methods = mono_image_alloc (class->image, sizeof (MonoMethod*) * class->method.count);
                for (i = 0; i < class->method.count; ++i) {
                        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);
@@ -1616,7 +1664,7 @@ mono_class_setup_properties (MonoClass *class)
                if (class->property.count)
                        mono_class_setup_methods (class);
 
-               properties = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoProperty) * class->property.count);
+               properties = mono_image_alloc0 (class->image, sizeof (MonoProperty) * class->property.count);
                for (i = class->property.first; i < last; ++i) {
                        mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
                        properties [i - class->property.first].parent = class;
@@ -1648,6 +1696,8 @@ mono_class_setup_properties (MonoClass *class)
                        }
                }
        }
+       /*Flush any pending writes as we do double checked locking on class->properties */
+       mono_memory_barrier ();
 
        /* Leave this assignment as the last op in the function */
        class->properties = properties;
@@ -1726,7 +1776,7 @@ mono_class_setup_events (MonoClass *class)
        if (class->event.count)
                mono_class_setup_methods (class);
 
-       events = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoEvent) * class->event.count);
+       events = mono_image_alloc0 (class->image, sizeof (MonoEvent) * class->event.count);
        for (i = class->event.first; i < last; ++i) {
                MonoEvent *event = &events [i - class->event.first];
 
@@ -1777,6 +1827,9 @@ mono_class_setup_events (MonoClass *class)
                        }
                }
        }
+       /*Flush any pending writes as we do double checked locking on class->properties */
+       mono_memory_barrier ();
+
        /* Leave this assignment as the last op in the function */
        class->events = events;
 
@@ -2304,9 +2357,9 @@ setup_interface_offsets (MonoClass *class, int cur_slot)
                g_assert (class->interface_offsets_count == interface_offsets_count);
        } else {
                class->interface_offsets_count = interface_offsets_count;
-               class->interfaces_packed = mono_mempool_alloc (class->image->mempool, sizeof (MonoClass*) * interface_offsets_count);
-               class->interface_offsets_packed = mono_mempool_alloc (class->image->mempool, sizeof (guint16) * interface_offsets_count);
-               class->interface_bitmap = mono_mempool_alloc0 (class->image->mempool, (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0));
+               class->interfaces_packed = mono_image_alloc (class->image, sizeof (MonoClass*) * interface_offsets_count);
+               class->interface_offsets_packed = mono_image_alloc (class->image, sizeof (guint16) * interface_offsets_count);
+               class->interface_bitmap = mono_image_alloc0 (class->image, (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0));
                for (interface_offsets_count = 0, i = 0; i <= max_iid; i++) {
                        if (interface_offsets_full [i] != -1) {
                                class->interface_bitmap [i >> 3] |= (1 << (i & 7));
@@ -2367,11 +2420,12 @@ mono_class_setup_vtable (MonoClass *class)
        if (class->vtable)
                return;
 
+       /* This sets method->slot for all methods if this is an interface */
+       mono_class_setup_methods (class);
+
        if (MONO_CLASS_IS_INTERFACE (class))
                return;
 
-       mono_class_setup_methods (class);
-
        mono_loader_lock ();
 
        if (class->vtable) {
@@ -2433,10 +2487,8 @@ check_core_clr_override_method (MonoClass *class, MonoMethod *override, MonoMeth
        MonoSecurityCoreCLRLevel override_level = mono_security_core_clr_method_level (override, FALSE);
        MonoSecurityCoreCLRLevel base_level = mono_security_core_clr_method_level (base, FALSE);
 
-       if (override_level != base_level && base_level == MONO_SECURITY_CORE_CLR_CRITICAL) {
-               class->exception_type = MONO_EXCEPTION_TYPE_LOAD;
-               class->exception_data = NULL;
-       }
+       if (override_level != base_level && base_level == MONO_SECURITY_CORE_CLR_CRITICAL)
+               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
 }
 
 
@@ -3275,7 +3327,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                mono_memory_barrier ();
                class->vtable = class->parent->vtable;
        } else {
-               MonoMethod **tmp = mono_mempool_alloc0 (class->image->mempool, sizeof (gpointer) * class->vtable_size);
+               MonoMethod **tmp = mono_image_alloc0 (class->image, sizeof (gpointer) * class->vtable_size);
                memcpy (tmp, vtable,  sizeof (gpointer) * class->vtable_size);
                mono_memory_barrier ();
                class->vtable = tmp;
@@ -3412,7 +3464,7 @@ generic_array_methods (MonoClass *class)
                        g_assert_not_reached ();
                }
 
-               name = mono_mempool_alloc (mono_defaults.corlib->mempool, strlen (iname) + strlen (mname) + 1);
+               name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
                strcpy (name, iname);
                strcpy (name + strlen (iname), mname);
                generic_array_method_info [i].name = name;
@@ -3444,10 +3496,10 @@ setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **met
 }
 
 static char*
-concat_two_strings_with_zero (MonoMemPool *pool, const char *s1, const char *s2)
+concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
 {
        int len = strlen (s1) + strlen (s2) + 2;
-       char *s = mono_mempool_alloc (pool, len);
+       char *s = mono_image_alloc (image, len);
        int result;
 
        result = g_snprintf (s, len, "%s%c%s", s1, '\0', s2);
@@ -3459,15 +3511,15 @@ concat_two_strings_with_zero (MonoMemPool *pool, const char *s1, const char *s2)
 static void
 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
 {
-       class->exception_type = error->exception_type;
+       gpointer exception_data = NULL;
 
        switch (error->exception_type) {
        case MONO_EXCEPTION_TYPE_LOAD:
-               class->exception_data = concat_two_strings_with_zero (class->image->mempool, error->class_name, error->assembly_name);
+               exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
                break;
 
        case MONO_EXCEPTION_MISSING_METHOD:
-               class->exception_data = concat_two_strings_with_zero (class->image->mempool, error->class_name, error->member_name);
+               exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
                break;
 
        case MONO_EXCEPTION_MISSING_FIELD: {
@@ -3479,7 +3531,7 @@ set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
                else
                        class_name = error->klass->name;
 
-               class->exception_data = concat_two_strings_with_zero (class->image->mempool, class_name, error->member_name);
+               exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
                
                if (name_space)
                        g_free ((void*)class_name);
@@ -3494,17 +3546,19 @@ set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
                else
                        msg = "Could not load file or assembly '%s' or one of its dependencies.";
 
-               class->exception_data = concat_two_strings_with_zero (class->image->mempool, msg, error->assembly_name);
+               exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
                break;
        }
 
        case MONO_EXCEPTION_BAD_IMAGE:
-               class->exception_data = error->msg;
+               exception_data = error->msg;
                break;
 
        default :
                g_assert_not_reached ();
        }
+
+       mono_class_set_failure (class, error->exception_type, exception_data);
 }
 
 static void
@@ -3519,10 +3573,8 @@ check_core_clr_inheritance (MonoClass *class)
        class_level = mono_security_core_clr_class_level (class);
        parent_level = mono_security_core_clr_class_level (parent);
 
-       if (class_level < parent_level) {
-               class->exception_type = MONO_EXCEPTION_TYPE_LOAD;
-               class->exception_data = NULL;
-       }
+       if (class_level < parent_level)
+               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
 }
 
 /**
@@ -3602,18 +3654,8 @@ mono_class_init (MonoClass *class)
 
        has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
 
-       if (!class->generic_class && !class->image->dynamic && (!has_cached_info || (has_cached_info && cached_info.has_nested_classes))) {
-               i = mono_metadata_nesting_typedef (class->image, class->type_token, 1);
-               while (i) {
-                       MonoClass* nclass;
-                       guint32 cols [MONO_NESTED_CLASS_SIZE];
-                       mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
-                       nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
-                       class->nested_classes = g_list_prepend_mempool (class->nested_classes, class->image->mempool, nclass);
-
-                       i = mono_metadata_nesting_typedef (class->image, class->type_token, i + 1);
-               }
-       }
+       if (class->generic_class || class->image->dynamic || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
+               class->nested_classes_inited = TRUE;
 
        /*
         * Computes the size used by the fields, and their locations
@@ -3701,7 +3743,8 @@ mono_class_init (MonoClass *class)
                }
                */
 
-               if (!MONO_CLASS_IS_INTERFACE (class)) {
+               /* Interfaces and valuetypes are not supposed to have finalizers */
+               if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
                        MonoMethod *cmethod = NULL;
 
                        if (class->type_token) {
@@ -3786,7 +3829,7 @@ mono_class_init (MonoClass *class)
        }
 
        if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
-               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image->mempool, class->name, class->image->assembly_name));
+               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
                class_init_ok = FALSE;
        }
 
@@ -4063,7 +4106,7 @@ mono_class_setup_supertypes (MonoClass *class)
                class->idepth = 1;
 
        ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
-       class->supertypes = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClass *) * ms);
+       class->supertypes = mono_image_alloc0 (class->image, sizeof (MonoClass *) * ms);
 
        if (class->parent) {
                class->supertypes [class->idepth - 1] = class;
@@ -4110,7 +4153,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
        nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
 
-       class = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
+       class = mono_image_alloc0 (image, sizeof (MonoClass));
 
        class->name = name;
        class->name_space = nspace;
@@ -4391,12 +4434,12 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb
                /* FIXME: */
                image = mono_defaults.corlib;
 
-       klass = param->pklass = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
+       klass = param->pklass = mono_image_alloc0 (image, sizeof (MonoClass));
 
        if (param->name)
                klass->name = param->name;
        else {
-               klass->name = mono_mempool_alloc0 (image->mempool, 16);
+               klass->name = mono_image_alloc0 (image, 16);
                sprintf ((char*)klass->name, is_mvar ? "!!%d" : "!%d", param->num);
        }
        klass->name_space = "";
@@ -4416,7 +4459,7 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb
 
        if (count - pos > 0) {
                klass->interface_count = count - pos;
-               klass->interfaces = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass *) * (count - pos));
+               klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
                for (i = pos; i < count; i++)
                        klass->interfaces [i - pos] = param->constraints [i];
        }
@@ -4489,12 +4532,12 @@ mono_ptr_class_get (MonoType *type)
                mono_loader_unlock ();
                return result;
        }
-       result = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
+       result = mono_image_alloc0 (image, sizeof (MonoClass));
 
        result->parent = NULL; /* no parent for PTR types */
        result->name_space = el_class->name_space;
        name = g_strdup_printf ("%s*", el_class->name);
-       result->name = mono_mempool_strdup (image->mempool, name);
+       result->name = mono_image_strdup (image, name);
        g_free (name);
 
        mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
@@ -4645,15 +4688,17 @@ mono_class_from_mono_type (MonoType *type)
  * @context: the generic context used to evaluate generic instantiations in
  */
 static MonoType *
-mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context)
+mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate)
 {
        MonoType *t = mono_type_create_from_typespec (image, type_spec);
        if (!t)
                return NULL;
        if (context && (context->class_inst || context->method_inst)) {
-               MonoType *inflated = inflate_generic_type (t, context);
-               if (inflated)
+               MonoType *inflated = inflate_generic_type (NULL, t, context);
+               if (inflated) {
                        t = inflated;
+                       *did_inflate = TRUE;
+               }
        }
        return t;
 }
@@ -4667,10 +4712,15 @@ mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGener
 static MonoClass *
 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context)
 {
-       MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context);
+       MonoClass *ret;
+       gboolean inflated = FALSE;
+       MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated);
        if (!t)
                return NULL;
-       return mono_class_from_mono_type (t);
+       ret = mono_class_from_mono_type (t);
+       if (inflated)
+               mono_metadata_free_type (t);
+       return ret;
 }
 
 /**
@@ -4726,7 +4776,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
                        mono_class_init (parent);
        }
 
-       class = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
+       class = mono_image_alloc0 (image, sizeof (MonoClass));
 
        class->image = image;
        class->name_space = eclass->name_space;
@@ -4740,7 +4790,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
                name [nsize + rank] = '*';
        name [nsize + rank + bounded] = ']';
        name [nsize + rank + bounded + 1] = 0;
-       class->name = mono_mempool_strdup (image->mempool, name);
+       class->name = mono_image_strdup (image, name);
        g_free (name);
 
        mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
@@ -4769,7 +4819,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
 
                /* generic IList, ICollection, IEnumerable */
                class->interface_count = 1;
-               class->interfaces = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass*) * class->interface_count);
+               class->interfaces = mono_image_alloc0 (image, sizeof (MonoClass*) * class->interface_count);
 
                args [0] = &eclass->byval_arg;
                class->interfaces [0] = mono_class_bind_generic_parameters (
@@ -4792,7 +4842,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
        class->element_class = eclass;
 
        if ((rank > 1) || bounded) {
-               MonoArrayType *at = mono_mempool_alloc0 (image->mempool, sizeof (MonoArrayType));
+               MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
                class->byval_arg.type = MONO_TYPE_ARRAY;
                class->byval_arg.data.array = at;
                at->eklass = eclass;
@@ -5257,6 +5307,7 @@ MonoType *
 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
 {
        MonoType *type = NULL;
+       gboolean inflated = FALSE;
 
        //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
        if (image->dynamic)
@@ -5267,14 +5318,30 @@ mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *co
                return class ? mono_class_get_type (class) : NULL;
        }
 
-       type = mono_type_retrieve_from_typespec (image, type_token, context);
+       type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated);
 
        if (!type) {
                char *name = mono_class_name_from_token (image, type_token);
                char *assembly = mono_assembly_name_from_token (image, type_token);
+               if (inflated)
+                       mono_metadata_free_type (type);
                mono_loader_set_error_type_load (name, assembly);
        }
 
+       if (inflated) {
+               MonoType *tmp = type;
+               type = mono_class_get_type (mono_class_from_mono_type (type));
+               /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
+                * A MonoClass::byval_arg of a generic type definion has type CLASS.
+                * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
+                *
+                * The long term solution is to chaise this places and make then set MonoType::type correctly.
+                * */
+               if (type->type != tmp->type)
+                       type = tmp;
+               else
+                       mono_metadata_free_type (tmp);
+       }
        return type;
 }
 
@@ -5474,17 +5541,18 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char
 }
 
 static MonoClass*
-return_nested_in (MonoClass *class, char *nested) {
+return_nested_in (MonoClass *class, char *nested)
+{
        MonoClass *found;
        char *s = strchr (nested, '/');
-       GList *tmp;
+       gpointer iter = NULL;
 
        if (s) {
                *s = 0;
                s++;
        }
-       for (tmp = class->nested_classes; tmp; tmp = tmp->next) {
-               found = tmp->data;
+
+       while ((found = mono_class_get_nested_types (class, &iter))) {
                if (strcmp (found->name, nested) == 0) {
                        if (s)
                                return return_nested_in (found, s);
@@ -5494,6 +5562,36 @@ return_nested_in (MonoClass *class, char *nested) {
        return NULL;
 }
 
+static MonoClass*
+search_modules (MonoImage *image, const char *name_space, const char *name)
+{
+       MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
+       MonoImage *file_image;
+       MonoClass *class;
+       int i;
+
+       /* 
+        * The EXPORTEDTYPES table only contains public types, so have to search the
+        * modules as well.
+        * Note: image->modules contains the contents of the MODULEREF table, while
+        * the real module list is in the FILE table.
+        */
+       for (i = 0; i < file_table->rows; i++) {
+               guint32 cols [MONO_FILE_SIZE];
+               mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
+               if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
+                       continue;
+
+               file_image = mono_image_load_file_for_image (image, i + 1);
+               if (file_image) {
+                       class = mono_class_from_name (file_image, name_space, name);
+                       if (class)
+                               return class;
+               }
+       }
+
+       return NULL;
+}
 
 /**
  * mono_class_from_name:
@@ -5529,6 +5627,8 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
        if (get_class_from_name) {
                gboolean res = get_class_from_name (image, name_space, name, &class);
                if (res) {
+                       if (!class)
+                               class = search_modules (image, name_space, name);
                        if (nested)
                                return class ? return_nested_in (class, nested) : NULL;
                        else
@@ -5559,6 +5659,12 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
                }
        }
 
+       if (!token) {
+               class = search_modules (image, name_space, name);
+               if (class)
+                       return class;
+       }
+
        if (!token)
                return NULL;
 
@@ -5582,15 +5688,19 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
                        return class;
                } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
                        MonoAssembly **references = image->references;
-                       if (!references [idx - 1])
-                               mono_assembly_load_reference (image, idx - 1);
+                       guint32 assembly_idx;
+
+                       assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
+
+                       if (!references [assembly_idx - 1])
+                               mono_assembly_load_reference (image, assembly_idx - 1);
                        g_assert (references == image->references);
-                       g_assert (references [idx - 1]);
-                       if (references [idx - 1] == (gpointer)-1)
+                       g_assert (references [assembly_idx - 1]);
+                       if (references [assembly_idx - 1] == (gpointer)-1)
                                return NULL;                    
                        else
                                /* FIXME: Cycle detection */
-                               return mono_class_from_name (references [idx - 1]->image, name_space, name);
+                               return mono_class_from_name (references [assembly_idx - 1]->image, name_space, name);
                } else {
                        g_error ("not yet implemented");
                }
@@ -5684,7 +5794,9 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
                         * interface_offsets set.
                         */
                        return mono_reflection_call_is_assignable_to (oklass, klass);
-
+               if (!oklass->interface_bitmap)
+                       /* Happens with generic instances of not-yet created dynamic types */
+                       return FALSE;
                if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
                        return TRUE;
 
@@ -5765,9 +5877,12 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
                }
 
                return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
-       } else if (mono_class_is_nullable (klass))
-               return (mono_class_is_assignable_from (klass->cast_class, oklass));
-       else if (klass == mono_defaults.object_class)
+       } else if (mono_class_is_nullable (klass)) {
+               if (mono_class_is_nullable (oklass))
+                       return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
+               else
+                       return mono_class_is_assignable_from (klass->cast_class, oklass);
+       } else if (klass == mono_defaults.object_class)
                return TRUE;
 
        return mono_class_has_parent (oklass, klass);
@@ -6275,8 +6390,8 @@ mono_class_get_fields (MonoClass* klass, gpointer *iter)
        MonoClassField* field;
        if (!iter)
                return NULL;
-       mono_class_setup_fields_locking (klass);
        if (!*iter) {
+               mono_class_setup_fields_locking (klass);
                /* start from the first */
                if (klass->field.count) {
                        return *iter = &klass->fields [0];
@@ -6465,10 +6580,33 @@ MonoClass*
 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
 {
        GList *item;
+       int i;
+
        if (!iter)
                return NULL;
        if (!klass->inited)
                mono_class_init (klass);
+       if (!klass->nested_classes_inited) {
+               if (!klass->type_token)
+                       klass->nested_classes_inited = TRUE;
+               mono_loader_lock ();
+               if (!klass->nested_classes_inited) {
+                       i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
+                       while (i) {
+                               MonoClass* nclass;
+                               guint32 cols [MONO_NESTED_CLASS_SIZE];
+                               mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
+                               nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
+                               klass->nested_classes = g_list_prepend_mempool (klass->nested_classes, klass->image->mempool, nclass);
+
+                               i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
+                       }
+               }
+               mono_memory_barrier ();
+               klass->nested_classes_inited = TRUE;
+               mono_loader_unlock ();
+       }
+
        if (!*iter) {
                /* start from the first */
                if (klass->nested_classes) {
@@ -6790,17 +6928,42 @@ mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int p
  *
  * Keep a detected failure informations in the class for later processing.
  * Note that only the first failure is kept.
+ *
+ * LOCKING: Acquires the loader lock.
  */
 gboolean
 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
 {
        if (klass->exception_type)
                return FALSE;
+
+       mono_loader_lock ();
        klass->exception_type = ex_type;
-       klass->exception_data = ex_data;
+       if (ex_data)
+               mono_property_hash_insert (klass->image->property_hash, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
+       mono_loader_unlock ();
+
        return TRUE;
 }
 
+/*
+ * mono_class_get_exception_data:
+ *
+ *   Return the exception_data property of KLASS.
+ *
+ * LOCKING: Acquires the loader lock.
+ */
+gpointer
+mono_class_get_exception_data (MonoClass *klass)
+{
+       gpointer res;
+
+       mono_loader_lock ();
+       res = mono_property_hash_lookup (klass->image->property_hash, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
+       mono_loader_unlock ();
+       return res;
+}
+
 /**
  * mono_classes_init:
  *
@@ -6834,11 +6997,13 @@ mono_classes_cleanup (void)
 MonoException*
 mono_class_get_exception_for_failure (MonoClass *klass)
 {
+       gpointer exception_data = mono_class_get_exception_data (klass);
+
        switch (klass->exception_type) {
        case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
                MonoDomain *domain = mono_domain_get ();
                MonoSecurityManager* secman = mono_security_manager_get_methods ();
-               MonoMethod *method = klass->exception_data;
+               MonoMethod *method = exception_data;
                guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
                MonoObject *exc = NULL;
                gpointer args [4];
@@ -6863,19 +7028,19 @@ mono_class_get_exception_for_failure (MonoClass *klass)
                return ex;
        }
        case MONO_EXCEPTION_MISSING_METHOD: {
-               char *class_name = klass->exception_data;
+               char *class_name = exception_data;
                char *assembly_name = class_name + strlen (class_name) + 1;
 
                return mono_get_exception_missing_method (class_name, assembly_name);
        }
        case MONO_EXCEPTION_MISSING_FIELD: {
-               char *class_name = klass->exception_data;
+               char *class_name = exception_data;
                char *member_name = class_name + strlen (class_name) + 1;
 
                return mono_get_exception_missing_field (class_name, member_name);
        }
        case MONO_EXCEPTION_FILE_NOT_FOUND: {
-               char *msg_format = klass->exception_data;
+               char *msg_format = exception_data;
                char *assembly_name = msg_format + strlen (msg_format) + 1;
                char *msg = g_strdup_printf (msg_format, assembly_name);
                MonoException *ex;
@@ -6887,7 +7052,7 @@ mono_class_get_exception_for_failure (MonoClass *klass)
                return ex;
        }
        case MONO_EXCEPTION_BAD_IMAGE: {
-               return mono_get_exception_bad_image_format (klass->exception_data);
+               return mono_get_exception_bad_image_format (exception_data);
        }
        default: {
                MonoLoaderError *error;
@@ -6908,6 +7073,8 @@ mono_class_get_exception_for_failure (MonoClass *klass)
 static gboolean
 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
  {
+       outer_klass = mono_class_get_generic_type_definition (outer_klass);
+       inner_klass = mono_class_get_generic_type_definition (inner_klass);
        do {
                if (outer_klass == inner_klass)
                        return TRUE;
@@ -6916,7 +7083,7 @@ is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
        return FALSE;
 }
 
-static MonoClass *
+MonoClass *
 mono_class_get_generic_type_definition (MonoClass *klass)
 {
        return klass->generic_class ? klass->generic_class->container_class : klass;
@@ -6979,6 +7146,7 @@ can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
                return TRUE;
        if (!accessed || !accessing)
                return FALSE;
+       mono_assembly_load_friends (accessed);
        for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
                MonoAssemblyName *friend = tmp->data;
                /* Be conservative with checks */
@@ -7018,7 +7186,10 @@ can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
 {
        int i;
        for (i = 0; i < ginst->type_argc; ++i) {
-               if (!can_access_type (access_klass, mono_class_from_mono_type (ginst->type_argv[i])))
+               MonoType *type = ginst->type_argv[i];
+               if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)
+                       continue;
+               if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
                        return FALSE;
        }
        return TRUE;
@@ -7326,19 +7497,28 @@ mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
 gboolean
 mono_class_generic_sharing_enabled (MonoClass *class)
 {
-#if defined(__i386__) || defined(__x86_64__)
-       static int generic_sharing = MONO_GENERIC_SHARING_CORLIB;
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+       static gboolean supported = TRUE;
 #else
-       static int generic_sharing = MONO_GENERIC_SHARING_NONE;
+       /* Not supported by the JIT backends */
+       static gboolean supported = FALSE;
 #endif
+       static int generic_sharing = MONO_GENERIC_SHARING_NONE;
        static gboolean inited = FALSE;
 
        if (!inited) {
                const char *option;
 
+               if (supported)
+                       generic_sharing = MONO_GENERIC_SHARING_CORLIB;
+               else
+                       generic_sharing = MONO_GENERIC_SHARING_NONE;
+
                if ((option = g_getenv ("MONO_GENERIC_SHARING"))) {
                        if (strcmp (option, "corlib") == 0)
                                generic_sharing = MONO_GENERIC_SHARING_CORLIB;
+                       else if (strcmp (option, "collections") == 0)
+                               generic_sharing = MONO_GENERIC_SHARING_COLLECTIONS;
                        else if (strcmp (option, "all") == 0)
                                generic_sharing = MONO_GENERIC_SHARING_ALL;
                        else if (strcmp (option, "none") == 0)
@@ -7347,6 +7527,9 @@ mono_class_generic_sharing_enabled (MonoClass *class)
                                g_warning ("Unknown generic sharing option `%s'.", option);
                }
 
+               if (!supported)
+                       generic_sharing = MONO_GENERIC_SHARING_NONE;
+
                inited = TRUE;
        }
 
@@ -7357,6 +7540,12 @@ mono_class_generic_sharing_enabled (MonoClass *class)
                return TRUE;
        case MONO_GENERIC_SHARING_CORLIB :
                return class->image == mono_defaults.corlib;
+       case MONO_GENERIC_SHARING_COLLECTIONS:
+               if (class->image != mono_defaults.corlib)
+                       return FALSE;
+               while (class->nested_in)
+                       class = class->nested_in;
+               return g_str_has_prefix (class->name_space, "System.Collections.Generic");
        default:
                g_assert_not_reached ();
        }