2009-09-03 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / class.c
index f4fabd974a0d99036081c575388ef93138ff032c..3d06a285dee79245d9a44ce1ce65faac71a74d73 100644 (file)
@@ -121,6 +121,9 @@ 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)
+                       return NULL;
+
                if (enclosing->nested_classes_inited && enclosing->ext) {
                        /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
                        for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
@@ -387,7 +390,7 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
 }
 
 /**
- * mono_type_get_name:
+ * mono_type_get_name_full:
  * @type: a type
  * @format: the format for the return string.
  *
@@ -497,9 +500,11 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont
                MonoGenericInst *inst = context->method_inst;
                if (!inst || !inst->type_argv)
                        return NULL;
-               if (num >= inst->type_argc)
+               if (num >= inst->type_argc) {
+                       MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
                        g_error ("MVAR %d (%s) cannot be expanded in this context with %d instantiations",
-                               num, mono_generic_param_info (type->data.generic_param)->name, inst->type_argc);
+                               num, info ? info->name : "", inst->type_argc);
+               }
 
                /*
                 * Note that the VAR/MVAR cases are different from the rest.  The other cases duplicate @type,
@@ -517,9 +522,11 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont
                MonoGenericInst *inst = context->class_inst;
                if (!inst)
                        return NULL;
-               if (num >= inst->type_argc)
+               if (num >= inst->type_argc) {
+                       MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
                        g_error ("VAR %d (%s) cannot be expanded in this context with %d instantiations",
-                               num, mono_generic_param_info (type->data.generic_param)->name, inst->type_argc);
+                               num, info ? info->name : "", inst->type_argc);
+               }
                nt = mono_metadata_type_dup (image, inst->type_argv [num]);
                nt->byref = type->byref;
                nt->attrs = type->attrs;
@@ -757,7 +764,7 @@ mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *conte
 }
 
 /**
- * mono_class_inflate_generic_method:
+ * mono_class_inflate_generic_method_full:
  *
  * Instantiate method @method with the generic context @context.
  * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
@@ -990,12 +997,22 @@ mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* con
 static MonoType*
 mono_class_find_enum_basetype (MonoClass *class)
 {
+       MonoGenericContainer *container = NULL;
        MonoImage *m = class->image; 
        const int top = class->field.count;
        int i;
 
        g_assert (class->enumtype);
 
+       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);
+       }
+
        /*
         * Fetch all the field information.
         */
@@ -1003,23 +1020,23 @@ mono_class_find_enum_basetype (MonoClass *class)
                const char *sig;
                guint32 cols [MONO_FIELD_SIZE];
                int idx = class->field.first + i;
-               MonoGenericContainer *container = NULL;
                MonoType *ftype;
 
                /* class->field.first and idx points into the fieldptr table */
                mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
+
+               if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
+                       continue;
+
+               if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL))
+                       return NULL;
+
                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;
+               if (*sig != 0x06)
+                       return NULL;
 
-                       container = gklass->generic_container;
-                       g_assert (container);
-               }
                ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
                if (!ftype)
                        return NULL;
@@ -1029,8 +1046,7 @@ mono_class_find_enum_basetype (MonoClass *class)
                        ftype->attrs = cols [MONO_FIELD_FLAGS];
                }
 
-               if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC))
-                       return ftype;
+               return ftype;
        }
 
        return NULL;
@@ -1055,7 +1071,7 @@ mono_class_setup_fields (MonoClass *class)
        gboolean explicit_size;
        MonoClassField *field;
        MonoGenericContainer *container = NULL;
-       MonoClass *gklass = NULL;
+       MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
 
        if (class->size_inited)
                return;
@@ -1070,12 +1086,16 @@ mono_class_setup_fields (MonoClass *class)
                return;
        }
 
-       if (class->generic_class) {
-               MonoClass *gklass = class->generic_class->container_class;
-               mono_class_setup_fields (gklass);
-               top = gklass->field.count;
-               class->field.first = gklass->field.first;
-               class->field.count = gklass->field.count;
+       if (gtd) {
+               mono_class_setup_fields (gtd);
+               if (gtd->exception_type) {
+                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       return;
+               }
+
+               top = gtd->field.count;
+               class->field.first = gtd->field.first;
+               class->field.count = gtd->field.count;
        }
 
        class->instance_size = 0;
@@ -1133,17 +1153,9 @@ mono_class_setup_fields (MonoClass *class)
 
        if (class->generic_container) {
                container = class->generic_container;
-       } else if (class->generic_class) {
-               gklass = class->generic_class->container_class;
-               container = gklass->generic_container;
+       } else if (gtd) {
+               container = gtd->generic_container;
                g_assert (container);
-
-               mono_class_setup_fields (gklass);
-
-               if (gklass->exception_type) {
-                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
-                       return;
-               }
        }
 
        /*
@@ -1155,8 +1167,8 @@ mono_class_setup_fields (MonoClass *class)
 
                field->parent = class;
 
-               if (class->generic_class) {
-                       MonoClassField *gfield = &gklass->fields [i];
+               if (gtd) {
+                       MonoClassField *gfield = &gtd->fields [i];
 
                        field->name = mono_field_get_name (gfield);
                        /*This memory must come from the image mempool as we don't have a chance to free it.*/
@@ -1173,6 +1185,10 @@ mono_class_setup_fields (MonoClass *class)
                        mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
                        /* The name is needed for fieldrefs */
                        field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
+                       if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
+                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                               break;
+                       }
                        sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
                        mono_metadata_decode_value (sig, &sig);
                        /* FIELD signature == 0x06 */
@@ -1790,6 +1806,19 @@ mono_class_get_vtable_entry (MonoClass *class, int offset)
        return m;
 }
 
+/*
+ * mono_class_get_vtable_size:
+ *
+ *   Return the vtable size for KLASS.
+ */
+int
+mono_class_get_vtable_size (MonoClass *klass)
+{
+       mono_class_setup_vtable (klass);
+
+       return klass->vtable_size;
+}
+
 static void
 mono_class_setup_properties (MonoClass *class)
 {
@@ -2244,7 +2273,7 @@ fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *ecla
  *     Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
  *     a != b ==> true
  * 
- * Fixing this should kill quite some code, save some bits and improve compatbility.
+ * Fixing this should kill quite some code, save some bits and improve compatibility.
  */
 static MonoClass**
 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
@@ -2442,6 +2471,37 @@ find_array_interface (MonoClass *klass, const char *name)
        return -1;
 }
 
+/*
+ * Return the number of virtual methods.
+ * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
+ * FIXME It would be nice if this information could be cached somewhere.
+ */
+static int
+count_virtual_methods (MonoClass *class)
+{
+       int i, count = 0;
+       guint32 flags;
+       class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
+
+       if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
+               mono_class_setup_methods (class);
+
+               for (i = 0; i < class->method.count; ++i) {
+                       flags = class->methods [i]->flags;
+                       if (flags & METHOD_ATTRIBUTE_VIRTUAL)
+                               ++count;
+               }
+       } else {
+               for (i = 0; i < class->method.count; ++i) {
+                       flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
+
+                       if (flags & METHOD_ATTRIBUTE_VIRTUAL)
+                               ++count;
+               }
+       }
+       return count;
+}
+
 /*
  * LOCKING: this is supposed to be called with the loader lock held.
  */
@@ -2512,9 +2572,11 @@ setup_interface_offsets (MonoClass *class, int cur_slot)
        if (ifaces) {
                for (i = 0; i < ifaces->len; ++i) {
                        ic = g_ptr_array_index (ifaces, i);
+                       if (interfaces_full [ic->interface_id] != NULL)
+                               continue;
                        interfaces_full [ic->interface_id] = ic;
                        interface_offsets_full [ic->interface_id] = cur_slot;
-                       cur_slot += ic->method.count;
+                       cur_slot += count_virtual_methods (ic);
                }
                g_ptr_array_free (ifaces, TRUE);
        }
@@ -3016,15 +3078,18 @@ static void
 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
        int index;
        char *method_signature;
+       char *type_name;
        
        for (index = 0; index < onum; ++index) {
                g_print (" at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name, 
                         overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
        }
        method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
-       printf ("no implementation for interface method %s::%s(%s) in class %s.%s\n",
-               mono_type_get_name (&ic->byval_arg), im->name, method_signature, class->name_space, class->name);
+       type_name = mono_type_full_name (&class->byval_arg);
+       printf ("no implementation for interface method %s::%s(%s) in class %s\n",
+               mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
        g_free (method_signature);
+       g_free (type_name);
        mono_class_setup_methods (class);
        for (index = 0; index < class->method.count; ++index) {
                MonoMethod *cm = class->methods [index];
@@ -3035,6 +3100,68 @@ print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, Mono
        }
 }
 
+static gboolean
+verify_class_overrides (MonoClass *class, GPtrArray *ifaces, MonoMethod **overrides, int onum)
+{
+       int i;
+       gboolean found;
+
+       for (i = 0; i < onum; ++i) {
+               MonoMethod *decl = overrides [i * 2];
+               MonoMethod *body = overrides [i * 2 + 1];
+
+               if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
+                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
+                       return FALSE;
+               }
+
+               if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
+                       if (body->flags & METHOD_ATTRIBUTE_STATIC)
+                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
+                       else
+                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
+                       return FALSE;
+               }
+
+               if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
+                               if (body->flags & METHOD_ATTRIBUTE_STATIC)
+                                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
+                               else
+                                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
+                               return FALSE;
+                       }
+                       
+               found = FALSE;
+               /*We can't use mono_class_is_assignable_from since it requires the class to be fully initialized*/
+               if (ifaces) {
+                       int j;
+                       for (j = 0; j < ifaces->len; j++) {
+                               MonoClass *ic = g_ptr_array_index (ifaces, j);
+                               if (decl->klass == ic) {
+                                       found = TRUE;
+                                       break;
+                               }
+                       }
+               }
+
+               if (!found) {
+                       MonoClass *parent = class;
+                       while (parent) {
+                               if (decl->klass == parent) {
+                                       found = TRUE;
+                                       break;
+                               }
+                               parent = parent->parent;
+                       }
+               }
+
+               if (!found) {
+                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
+                       return FALSE;
+               }
+       }
+       return TRUE;
+}
 /*
  * LOCKING: this is supposed to be called with the loader lock held.
  */
@@ -3057,6 +3184,13 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                return;
 
        ifaces = mono_class_get_implemented_interfaces (class);
+
+       if (overrides && !verify_class_overrides (class, ifaces, overrides, onum)) {
+               if (ifaces)
+                       g_ptr_array_free (ifaces, TRUE);
+               return;
+       }
+
        if (ifaces) {
                for (i = 0; i < ifaces->len; i++) {
                        MonoClass *ic = g_ptr_array_index (ifaces, i);
@@ -3090,6 +3224,10 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                MonoMethod **tmp;
 
                mono_class_setup_vtable (gklass);
+               if (gklass->exception_type != MONO_EXCEPTION_NONE) {
+                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       return;
+               }
 
                tmp = mono_image_alloc0 (class->image, sizeof (gpointer) * gklass->vtable_size);
                class->vtable_size = gklass->vtable_size;
@@ -3368,6 +3506,20 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                g_hash_table_destroy (override_map);
        }
 
+       /* Ensure that all vtable slots are filled with concrete instance methods */
+       if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+               for (i = 0; i < cur_slot; ++i) {
+                       if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
+                               char *type_name = mono_type_get_full_name (class);
+                               char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
+                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
+                               g_free (type_name);
+                               g_free (method_name);
+                               return;
+                       }
+               }
+       }
+
        if (class->generic_class) {
                MonoClass *gklass = class->generic_class->container_class;
 
@@ -3929,7 +4081,6 @@ mono_class_init (MonoClass *class)
        if (mono_debugger_class_init_func)
                mono_debugger_class_init_func (class);
 
-       //printf ("class %s size %d\n", class->name, class->instance_size);
        return class_init_ok;
 }
 
@@ -4284,7 +4435,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 
        if (!class->enumtype) {
                if (!mono_metadata_interfaces_from_typedef_full (
-                           image, type_token, &interfaces, &icount, context)){
+                           image, type_token, &interfaces, &icount, FALSE, context)){
                        mono_loader_unlock ();
                        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
                        return NULL;
@@ -4334,7 +4485,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                class->method.count = 0;
 
        /* reserve space to store vector pointer in arrays */
-       if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
+       if (is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
                class->instance_size += 2 * sizeof (gpointer);
                g_assert (class->field.count == 0);
        }
@@ -4344,6 +4495,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                if (!enum_basetype) {
                        mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        mono_loader_unlock ();
+                       mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
                        return NULL;
                }
                class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
@@ -4354,9 +4506,15 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
         * 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 (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
+               char *class_name = g_strdup_printf("%s.%s", class->name_space, class->name);
+               char *error = concat_two_strings_with_zero (class->image, class_name, class->image->assembly_name);
+               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, error);
+               g_free (class_name);
+               mono_loader_unlock ();
+               mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+               return NULL;
+       }
 
        if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
                if (!strncmp (name, "Vector", 6))
@@ -4873,7 +5031,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
        MonoImage *image;
        MonoClass *class;
        MonoClass *parent = NULL;
-       GSList *list, *rootlist;
+       GSList *list, *rootlist = NULL;
        int nsize;
        char *name;
        gboolean corlib_type = FALSE;
@@ -5132,6 +5290,7 @@ mono_class_get_field_idx (MonoClass *class, int idx)
                         * class->field.first points to the FieldPtr table, while idx points into the
                         * Field table, so we have to do a search.
                         */
+                       /*FIXME this is broken for types with multiple fields with the same name.*/
                        const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
                        int i;
 
@@ -5181,14 +5340,42 @@ mono_class_get_field (MonoClass *class, guint32 field_token)
  */
 MonoClassField *
 mono_class_get_field_from_name (MonoClass *klass, const char *name)
+{
+       return mono_class_get_field_from_name_full (klass, name, NULL);
+}
+
+/**
+ * mono_class_get_field_from_name_full:
+ * @klass: the class to lookup the field.
+ * @name: the field name
+ * @type: the type of the fields. This optional.
+ *
+ * Search the class @klass and it's parents for a field with the name @name and type @type.
+ *
+ * If @klass is an inflated generic type, the type comparison is done with the equivalent field
+ * of its generic type definition.
+ *
+ * Returns: the MonoClassField pointer of the named field or NULL
+ */
+MonoClassField *
+mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
 {
        int i;
 
        mono_class_setup_fields_locking (klass);
        while (klass) {
                for (i = 0; i < klass->field.count; ++i) {
-                       if (strcmp (name, mono_field_get_name (&klass->fields [i])) == 0)
-                               return &klass->fields [i];
+                       MonoClassField *field = &klass->fields [i];
+
+                       if (strcmp (name, mono_field_get_name (field)) != 0)
+                               continue;
+
+                       if (type) {
+                               MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
+                               if (!mono_metadata_type_equal_full (type, field_type, TRUE))
+                                       continue;
+                       }
+                       return field;
                }
                klass = klass->parent;
        }
@@ -5536,7 +5723,7 @@ mono_class_get (MonoImage *image, guint32 type_token)
  *
  *  Initializes the class name cache stored in image->name_cache.
  *
- * LOCKING: Acquires the loader lock.
+ * LOCKING: Acquires the corresponding image lock.
  */
 void
 mono_image_init_name_cache (MonoImage *image)
@@ -5548,12 +5735,17 @@ mono_image_init_name_cache (MonoImage *image)
        guint32 i, visib, nspace_index;
        GHashTable *name_cache2, *nspace_table;
 
-       mono_loader_lock ();
+       mono_image_lock (image);
+
+       if (image->name_cache) {
+               mono_image_unlock (image);
+               return;
+       }
 
        image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
 
        if (image->dynamic) {
-               mono_loader_unlock ();
+               mono_image_unlock (image);
                return;
        }
 
@@ -5607,10 +5799,10 @@ mono_image_init_name_cache (MonoImage *image)
        }
 
        g_hash_table_destroy (name_cache2);
-
-       mono_loader_unlock ();
+       mono_image_unlock (image);
 }
 
+/*FIXME Only dynamic assemblies should allow this operation.*/
 void
 mono_image_add_to_name_cache (MonoImage *image, const char *nspace, 
                                                          const char *name, guint32 index)
@@ -5618,7 +5810,7 @@ mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
        GHashTable *nspace_table;
        GHashTable *name_cache;
 
-       mono_loader_lock ();
+       mono_image_lock (image);
 
        if (!image->name_cache)
                mono_image_init_name_cache (image);
@@ -5630,7 +5822,7 @@ mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
        }
        g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
 
-       mono_loader_unlock ();
+       mono_image_unlock (image);
 }
 
 typedef struct {
@@ -5671,7 +5863,7 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char
                guint32 token = 0;
                FindUserData user_data;
 
-               mono_loader_lock ();
+               mono_image_lock (image);
 
                if (!image->name_cache)
                        mono_image_init_name_cache (image);
@@ -5692,7 +5884,7 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char
                                token = GPOINTER_TO_UINT (user_data.value);
                }
 
-               mono_loader_unlock ();
+               mono_image_unlock (image);
                
                if (token)
                        return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
@@ -5815,7 +6007,7 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
                }
        }
 
-       mono_loader_lock ();
+       mono_image_lock (image);
 
        if (!image->name_cache)
                mono_image_init_name_cache (image);
@@ -5825,7 +6017,7 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
        if (nspace_table)
                token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
 
-       mono_loader_unlock ();
+       mono_image_unlock (image);
 
        if (!token && image->dynamic && image->modules) {
                /* Search modules as well */
@@ -5866,20 +6058,17 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
                                return return_nested_in (class, nested);
                        return class;
                } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
-                       MonoAssembly **references = image->references;
                        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 [assembly_idx - 1]);
-                       if (references [assembly_idx - 1] == (gpointer)-1)
+                       mono_assembly_load_reference (image, assembly_idx - 1);
+                       g_assert (image->references [assembly_idx - 1]);
+                       if (image->references [assembly_idx - 1] == (gpointer)-1)
                                return NULL;                    
                        else
                                /* FIXME: Cycle detection */
-                               return mono_class_from_name (references [assembly_idx - 1]->image, name_space, name);
+                               return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
                } else {
                        g_error ("not yet implemented");
                }
@@ -6131,7 +6320,7 @@ mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
        if (method)
                return (method == caller) ? FALSE : TRUE;
        else
-               return TRUE;
+               return FALSE;
 }
 
 /**
@@ -6185,6 +6374,10 @@ handle_enum:
        case MONO_TYPE_GENERICINST:
                type = &type->data.generic_class->container_class->byval_arg;
                goto handle_enum;
+
+       case MONO_TYPE_VOID:
+               return 0;
+               
        default:
                g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
        }
@@ -6907,7 +7100,7 @@ mono_field_get_type (MonoClassField *field)
 }
 
 /**
- * mono_field_get_type:
+ * mono_field_get_parent:
  * @field: the MonoClassField to act on
  *
  * Returns: MonoClass where the field was defined.
@@ -7540,6 +7733,10 @@ can_access_type (MonoClass *access_klass, MonoClass *member_klass)
        if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
                return FALSE;
 
+       /*Non nested type with nested visibility. We just fail it.*/
+       if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
+               return FALSE;
+
        switch (access_level) {
        case TYPE_ATTRIBUTE_NOT_PUBLIC:
                return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
@@ -7704,7 +7901,7 @@ mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, Mono
 
 
 /*
- * mono_method_can_access_method_with_context:
+ * mono_method_can_access_field_full:
  * @method: The caller method 
  * @field: The accessed field
  * @context_klass: The static type on stack of the owner @field object used