Merge pull request #2020 from tomjepp/master
[mono.git] / mono / metadata / class.c
index f508da0d2965d0fa4072a6a483a1d584713f1bb1..fdfd5c31505f0ffb427a0655627bf562f558ca27 100644 (file)
@@ -47,6 +47,7 @@
 MonoStats mono_stats;
 
 gboolean mono_print_vtable = FALSE;
+gboolean mono_align_small_structs = FALSE;
 
 /* Statistics */
 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
@@ -279,7 +280,7 @@ done:
                        mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
                }
        }
-       g_assert (!mono_loader_get_last_error ());
+       mono_loader_assert_no_error ();
        return res;
 }
 
@@ -631,7 +632,7 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont
                MonoType *nt;
                int num = mono_type_get_generic_param_num (type);
                MonoGenericInst *inst = context->method_inst;
-               if (!inst || !inst->type_argv)
+               if (!inst)
                        return NULL;
                if (num >= inst->type_argc) {
                        MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
@@ -1008,7 +1009,6 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
        MonoMethodInflated *iresult, *cached;
        MonoMethodSignature *sig;
        MonoGenericContext tmp_context;
-       gboolean is_mb_open = FALSE;
 
        mono_error_init (error);
 
@@ -1040,44 +1040,9 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
                (method->klass->generic_container && context->class_inst)))
                return method;
 
-       /*
-        * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
-        * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
-        * This is opposite to the way non-SRE MethodInfos behave.
-        * 
-        * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
-        * 
-        * void Example<T> () {
-        *    Example<T> ();
-        * }
-        *  
-        * In Example, the method token must be encoded as: "void Example<!!0>()"
-        * 
-        * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
-        * properly. To get that we need to inflate the MethodBuilder with its own arguments.
-        * 
-        * On the other hand, inflating a non-SRE generic method with its own arguments should
-        * return itself. For example:
-        * 
-        * MethodInfo m = ... //m is a generic method definition
-        * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
-        * res == m
-        *
-        * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
-        * what happens with regular methods.
-        * 
-        * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
-        * everything should behave like a regular type or method.
-        * 
-        */
-       is_mb_open = method->is_generic &&
-               image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
-               context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments.  */
-
        iresult = g_new0 (MonoMethodInflated, 1);
        iresult->context = *context;
        iresult->declaring = method;
-       iresult->method.method.is_mb_open = is_mb_open;
 
        if (!context->method_inst && method->is_generic)
                iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
@@ -1093,7 +1058,13 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
        if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
                iresult->context.class_inst = NULL;
 
-       cached = mono_method_inflated_lookup (iresult, FALSE);
+       MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
+
+       // check cache
+       mono_image_set_lock (set);
+       cached = g_hash_table_lookup (set->gmethod_cache, iresult);
+       mono_image_set_unlock (set);
+
        if (cached) {
                g_free (iresult);
                return (MonoMethod*)cached;
@@ -1122,7 +1093,6 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
        result->is_generic = FALSE;
        result->sre_method = FALSE;
        result->signature = NULL;
-       result->is_mb_open = is_mb_open;
 
        if (!context->method_inst) {
                /* Set the generic_container of the result to the generic_container of method */
@@ -1165,7 +1135,17 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
         * is_generic_method_definition().
         */
 
-       return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
+       // check cache
+       mono_image_set_lock (set);
+       cached = g_hash_table_lookup (set->gmethod_cache, iresult);
+       if (!cached) {
+               g_hash_table_insert (set->gmethod_cache, iresult, iresult);
+               iresult->owner = set;
+               cached = iresult;
+       }
+       mono_image_set_unlock (set);
+
+       return (MonoMethod*)cached;
 
 fail:
        g_free (iresult);
@@ -1334,7 +1314,7 @@ mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
        mono_error_set_type_load_class (error, class, "Could not find base type");
 
 fail:
-       g_assert (!mono_loader_get_last_error ());
+       mono_loader_assert_no_error ();
        return NULL;
 }
 
@@ -1596,7 +1576,7 @@ mono_class_setup_fields (MonoClass *class)
                return;
        }
 
-       if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+       if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (class->image) && !strcmp (class->name_space, "System") && !strcmp (class->name, "ValueType")))
                blittable = FALSE;
 
        /* Prevent infinite loops if the class references itself */
@@ -1771,6 +1751,20 @@ mono_type_get_basic_type_from_generic (MonoType *type)
        return type;
 }
 
+static gboolean
+type_has_references (MonoClass *klass, MonoType *ftype)
+{
+       if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+               return TRUE;
+       if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
+               MonoGenericParam *gparam = ftype->data.generic_param;
+
+               if (gparam->gshared_constraint)
+                       return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
+       }
+       return FALSE;
+}
+
 /*
  * mono_class_layout_fields:
  * @class: a class
@@ -1831,7 +1825,7 @@ mono_class_layout_fields (MonoClass *class)
                if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
                        ftype = mono_type_get_underlying_type (field->type);
                        ftype = mono_type_get_basic_type_from_generic (ftype);
-                       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 (type_has_references (class, ftype))
                                class->has_references = TRUE;
                }
        }
@@ -1844,7 +1838,7 @@ mono_class_layout_fields (MonoClass *class)
                if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
                        ftype = mono_type_get_underlying_type (field->type);
                        ftype = mono_type_get_basic_type_from_generic (ftype);
-                       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 (type_has_references (class, ftype))
                                class->has_static_refs = TRUE;
                }
        }
@@ -1856,7 +1850,7 @@ mono_class_layout_fields (MonoClass *class)
 
                ftype = mono_type_get_underlying_type (field->type);
                ftype = mono_type_get_basic_type_from_generic (ftype);
-               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 (type_has_references (class, ftype)) {
                        if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
                                class->has_static_refs = TRUE;
                        else
@@ -1907,7 +1901,7 @@ mono_class_layout_fields (MonoClass *class)
                                ftype = mono_type_get_underlying_type (field->type);
                                ftype = mono_type_get_basic_type_from_generic (ftype);
                                if (gc_aware_layout) {
-                                       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 (type_has_references (class, ftype)) {
                                                if (pass == 1)
                                                        continue;
                                        } else {
@@ -1929,7 +1923,7 @@ mono_class_layout_fields (MonoClass *class)
                                /* if the field has managed references, we need to force-align it
                                 * see bug #77788
                                 */
-                               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 (type_has_references (class, ftype))
                                        align = MAX (align, sizeof (gpointer));
 
                                class->min_align = MAX (align, class->min_align);
@@ -1984,7 +1978,7 @@ mono_class_layout_fields (MonoClass *class)
                        field->offset += sizeof (MonoObject);
                        ftype = mono_type_get_underlying_type (field->type);
                        ftype = mono_type_get_basic_type_from_generic (ftype);
-                       if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
+                       if (type_has_references (class, ftype)) {
                                if (field->offset % sizeof (gpointer)) {
                                        mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
                                }
@@ -2043,12 +2037,17 @@ mono_class_layout_fields (MonoClass *class)
 
        if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
                /*
+                * This leads to all kinds of problems with nested structs, so only
+                * enable it when a MONO_DEBUG property is set.
+                *
                 * For small structs, set min_align to at least the struct size to improve
                 * performance, and since the JIT memset/memcpy code assumes this and generates 
                 * unaligned accesses otherwise. See #78990 for a testcase.
                 */
-               if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
-                       class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
+               if (mono_align_small_structs) {
+                       if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
+                               class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
+               }
        }
 
        mono_memory_barrier ();
@@ -2067,6 +2066,9 @@ mono_class_layout_fields (MonoClass *class)
                        continue;
                if (mono_field_is_deleted (field))
                        continue;
+               // Special static fields do not need a domain-level static slot
+               if (mono_class_field_is_special_static (field))
+                       continue;
 
                if (mono_type_has_exceptions (field->type)) {
                        mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
@@ -3615,8 +3617,9 @@ setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
         * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
         * means we have to overwrite those when called from other places (#4440).
         */
-       if (class->interfaces_packed && !overwrite) {
-               g_assert (class->interface_offsets_count == interface_offsets_count);
+       if (class->interfaces_packed) {
+               if (!overwrite)
+                       g_assert (class->interface_offsets_count == interface_offsets_count);
        } else {
                uint8_t *bitmap;
                int bsize;
@@ -3909,7 +3912,8 @@ is_wcf_hack_disabled (void)
 }
 
 static gboolean
-check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty, gboolean security_enabled) {
+check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
+{
        MonoMethodSignature *cmsig, *imsig;
        if (strcmp (im->name, cm->name) == 0) {
                if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
@@ -3944,11 +3948,6 @@ check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *c
                        return FALSE;
                }
                TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
-               /* CAS - SecurityAction.InheritanceDemand on interface */
-               if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
-                       mono_secman_inheritancedemand_method (cm, im);
-               }
-
                if (mono_security_core_clr_enabled ())
                        mono_security_core_clr_check_override (class, cm, im);
 
@@ -4030,11 +4029,6 @@ check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *c
                }
                
                TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
-               /* CAS - SecurityAction.InheritanceDemand on interface */
-               if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
-                       mono_secman_inheritancedemand_method (cm, im);
-               }
-
                if (mono_security_core_clr_enabled ())
                        mono_security_core_clr_check_override (class, cm, im);
 
@@ -4267,7 +4261,6 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
        int i, max_vtsize = 0, max_iid, cur_slot = 0;
        GPtrArray *ifaces = NULL;
        GHashTable *override_map = NULL;
-       gboolean security_enabled = mono_security_enabled ();
        MonoMethod *cm;
 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
        int first_non_interface_slot;
@@ -4511,7 +4504,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                for (l = virt_methods; l; l = l->next) {
                                        cm = l->data;
                                        TRACE_INTERFACE_VTABLE (printf ("    For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL)));
-                                       if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
+                                       if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
                                                TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
                                                vtable [im_slot] = cm;
                                                /* Why do we need this? */
@@ -4532,7 +4525,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                                MonoMethod *cm = parent->vtable [cm_index];
                                                
                                                TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("    For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name));
-                                               if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
+                                               if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE)) {
                                                        TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
                                                        vtable [im_slot] = cm;
                                                        /* Why do we need this? */
@@ -4610,11 +4603,6 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                        if (!strcmp(cm->name, m1->name) && 
                                            mono_metadata_signature_equal (cmsig, m1sig)) {
 
-                                               /* CAS - SecurityAction.InheritanceDemand */
-                                               if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
-                                                       mono_secman_inheritancedemand_method (cm, m1);
-                                               }
-
                                                if (mono_security_core_clr_enabled ())
                                                        mono_security_core_clr_check_override (class, cm, m1);
 
@@ -4822,6 +4810,11 @@ mono_method_get_vtable_slot (MonoMethod *method)
                        MonoClass *gklass;
                        int i;
 
+                       if (!method->klass->generic_class) {
+                               g_assert (method->is_inflated);
+                               return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
+                       }
+
                        /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
                        g_assert (method->klass->generic_class);
                        gklass = method->klass->generic_class->container_class;
@@ -5104,11 +5097,6 @@ mono_class_init (MonoClass *class)
                }
        }
 
-       /* CAS - SecurityAction.InheritanceDemand */
-       if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
-               mono_secman_inheritancedemand_class (class, class->parent);
-       }
-
        mono_stats.initialized_class_count++;
 
        if (class->generic_class && !class->generic_class->is_dynamic) {
@@ -5738,7 +5726,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
 
        if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
                mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
-               g_assert (!mono_loader_get_last_error ());
+               mono_loader_assert_no_error ();
                return NULL;
        }
 
@@ -5746,7 +5734,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
 
        if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
                mono_loader_unlock ();
-               g_assert (!mono_loader_get_last_error ());
+               mono_loader_assert_no_error ();
                return class;
        }
 
@@ -5835,7 +5823,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
                        mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
                        mono_loader_unlock ();
                        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
-                       g_assert (!mono_loader_get_last_error ());
+                       mono_loader_assert_no_error ();
                        return NULL;
                }
        }
@@ -5907,7 +5895,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
                        mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
                        mono_loader_unlock ();
                        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
-                       g_assert (!mono_loader_get_last_error ());
+                       mono_loader_assert_no_error ();
                        return NULL;
                }
                class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
@@ -5922,7 +5910,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
                mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
                mono_loader_unlock ();
                mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
-               g_assert (!mono_loader_get_last_error ());
+               mono_loader_assert_no_error ();
                return NULL;
        }
 
@@ -5934,7 +5922,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
        mono_loader_unlock ();
 
        mono_profiler_class_loaded (class, MONO_PROFILE_OK);
-       g_assert (!mono_loader_get_last_error ());
+       mono_loader_assert_no_error ();
 
        return class;
 
@@ -5942,7 +5930,7 @@ parent_failure:
        mono_class_setup_mono_type (class);
        mono_loader_unlock ();
        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
-       g_assert (!mono_loader_get_last_error ());
+       mono_loader_assert_no_error ();
        return NULL;
 }
 
@@ -6540,7 +6528,7 @@ mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGener
                MonoType *inflated = inflate_generic_type (NULL, t, context, error);
 
                if (!mono_error_ok (error)) {
-                       g_assert (!mono_loader_get_last_error ());
+                       mono_loader_assert_no_error ();
                        return NULL;
                }
 
@@ -7402,7 +7390,7 @@ mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext
                MonoClass *class = mono_class_get_checked (image, type_token, error);
 
                if (!class) {
-                       g_assert (!mono_loader_get_last_error ());
+                       mono_loader_assert_no_error ();
                        return NULL;
                }
 
@@ -7413,7 +7401,7 @@ mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext
        type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
 
        if (!type) {
-               g_assert (!mono_loader_get_last_error ());
+               mono_loader_assert_no_error ();
                return NULL;
        }
 
@@ -7456,18 +7444,21 @@ mono_image_init_name_cache (MonoImage *image)
        const char *name;
        const char *nspace;
        guint32 i, visib, nspace_index;
-       GHashTable *name_cache2, *nspace_table;
+       GHashTable *name_cache2, *nspace_table, *the_name_cache;
 
-       mono_image_lock (image);
-
-       if (image->name_cache) {
-               mono_image_unlock (image);
+       if (image->name_cache)
                return;
-       }
 
-       image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
+       the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
 
        if (image_is_dynamic (image)) {
+               mono_image_lock (image);
+               if (image->name_cache) {
+                       /* Somebody initialized it before us */
+                       g_hash_table_destroy (the_name_cache);
+               } else {
+                       mono_atomic_store_release (&image->name_cache, the_name_cache);
+               }
                mono_image_unlock (image);
                return;
        }
@@ -7491,7 +7482,7 @@ mono_image_init_name_cache (MonoImage *image)
                nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
                if (!nspace_table) {
                        nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
-                       g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
+                       g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
                        g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
                                                                 nspace_table);
                }
@@ -7513,7 +7504,7 @@ mono_image_init_name_cache (MonoImage *image)
                        nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
                        if (!nspace_table) {
                                nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
-                               g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
+                               g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
                                g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
                                                                         nspace_table);
                        }
@@ -7522,6 +7513,14 @@ mono_image_init_name_cache (MonoImage *image)
        }
 
        g_hash_table_destroy (name_cache2);
+
+       mono_image_lock (image);
+       if (image->name_cache) {
+               /* Somebody initialized it before us */
+               g_hash_table_destroy (the_name_cache);
+       } else {
+               mono_atomic_store_release (&image->name_cache, the_name_cache);
+       }
        mono_image_unlock (image);
 }
 
@@ -7534,11 +7533,9 @@ mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
        GHashTable *name_cache;
        guint32 old_index;
 
+       mono_image_init_name_cache (image);
        mono_image_lock (image);
 
-       if (!image->name_cache)
-               mono_image_init_name_cache (image);
-
        name_cache = image->name_cache;
        if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
                nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
@@ -7603,11 +7600,9 @@ mono_class_from_name_case_checked (MonoImage *image, const char* name_space, con
                guint32 token = 0;
                FindUserData user_data;
 
+               mono_image_init_name_cache (image);
                mono_image_lock (image);
 
-               if (!image->name_cache)
-                       mono_image_init_name_cache (image);
-
                user_data.key = name_space;
                user_data.value = NULL;
                g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
@@ -7704,8 +7699,8 @@ search_modules (MonoImage *image, const char *name_space, const char *name)
        return NULL;
 }
 
-MonoClass *
-mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
+static MonoClass *
+mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
 {
        GHashTable *nspace_table;
        MonoImage *loaded_image;
@@ -7717,6 +7712,12 @@ mono_class_from_name_checked (MonoImage *image, const char* name_space, const ch
 
        mono_error_init (error);
 
+       // Checking visited images avoids stack overflows when cyclic references exist.
+       if (g_hash_table_lookup (visited_images, image))
+               return NULL;
+
+       g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
+
        if ((nested = strchr (name, '/'))) {
                int pos = nested - name;
                int len = strlen (name);
@@ -7741,11 +7742,9 @@ mono_class_from_name_checked (MonoImage *image, const char* name_space, const ch
                }
        }
 
+       mono_image_init_name_cache (image);
        mono_image_lock (image);
 
-       if (!image->name_cache)
-               mono_image_init_name_cache (image);
-
        nspace_table = g_hash_table_lookup (image->name_cache, name_space);
 
        if (nspace_table)
@@ -7787,7 +7786,7 @@ mono_class_from_name_checked (MonoImage *image, const char* name_space, const ch
                        loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
                        if (!loaded_image)
                                return NULL;
-                       class = mono_class_from_name (loaded_image, name_space, name);
+                       class = mono_class_from_name_checked_aux (loaded_image, name_space, name, error, visited_images);
                        if (nested)
                                return return_nested_in (class, nested);
                        return class;
@@ -7801,8 +7800,7 @@ mono_class_from_name_checked (MonoImage *image, const char* name_space, const ch
                        if (image->references [assembly_idx - 1] == (gpointer)-1)
                                return NULL;                    
                        else
-                               /* FIXME: Cycle detection */
-                               return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
+                               return mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, error, visited_images);
                } else {
                        g_error ("not yet implemented");
                }
@@ -7816,6 +7814,21 @@ mono_class_from_name_checked (MonoImage *image, const char* name_space, const ch
        return class;
 }
 
+MonoClass *
+mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
+{
+       MonoClass *klass;
+       GHashTable *visited_images;
+
+       visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+       klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
+
+       g_hash_table_destroy (visited_images);
+
+       return klass;
+}
+
 /**
  * mono_class_from_name:
  * @image: The MonoImage where the type is looked up in
@@ -9777,24 +9790,6 @@ mono_class_get_exception_for_failure (MonoClass *klass)
        gpointer exception_data = mono_class_get_exception_data (klass);
 
        switch (klass->exception_type) {
-#ifndef DISABLE_SECURITY
-       case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
-               MonoDomain *domain = mono_domain_get ();
-               MonoSecurityManager* secman = mono_security_manager_get_methods ();
-               MonoMethod *method = exception_data;
-               guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
-               MonoObject *exc = NULL;
-               gpointer args [4];
-
-               args [0] = &error;
-               args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
-               args [2] = mono_type_get_object (domain, &klass->byval_arg);
-               args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
-
-               mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
-               return (MonoException*) exc;
-       }
-#endif
        case MONO_EXCEPTION_TYPE_LOAD: {
                MonoString *name;
                MonoException *ex;