Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mono / metadata / class.c
index d56eca8c8c9e6fdc2ea0f5720589a341dab1eab9..bef40e06e5ac208f7320a5ff7cc381476fbff47f 100644 (file)
@@ -1403,6 +1403,8 @@ mono_class_setup_fields (MonoClass *class)
                }
                class->size_inited = 1;
                class->blittable = blittable;
+               mono_memory_barrier ();
+               class->fields_inited = 1;
                return;
        }
 
@@ -1518,6 +1520,9 @@ mono_class_setup_fields (MonoClass *class)
        /*valuetypes can't be neither bigger than 1Mb or empty. */
        if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
                mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+
+       mono_memory_barrier ();
+       class->fields_inited = 1;
 }
 
 /** 
@@ -1527,9 +1532,12 @@ mono_class_setup_fields (MonoClass *class)
  * Initializes the class->fields array of fields.
  * Aquires the loader lock.
  */
-static void
+void
 mono_class_setup_fields_locking (MonoClass *class)
 {
+       /* This can be checked without locks */
+       if (class->fields_inited)
+               return;
        mono_loader_lock ();
        mono_class_setup_fields (class);
        mono_loader_unlock ();
@@ -1769,6 +1777,7 @@ mono_class_layout_fields (MonoClass *class)
                                continue;
 
                        size = mono_type_size (field->type, &align);
+                       align = class->packing_size ? MIN (class->packing_size, align): align;
                        class->min_align = MAX (align, class->min_align);
 
                        /*
@@ -1792,6 +1801,10 @@ mono_class_layout_fields (MonoClass *class)
                        real_size = MAX (real_size, size + field->offset);
                }
                class->instance_size = MAX (real_size, class->instance_size);
+               if (class->instance_size & (class->min_align - 1)) {
+                       class->instance_size += class->min_align - 1;
+                       class->instance_size &= ~(class->min_align - 1);
+               }
                break;
        }
 
@@ -2722,7 +2735,8 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
                         */
                        eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
                        original_rank = eclass->rank;
-                       eclass = eclass->element_class;
+                       if (!eclass->rank)
+                               eclass = eclass->element_class;
                        internal_enumerator = TRUE;
                        *is_enumerator = TRUE;
                } else {
@@ -5734,7 +5748,7 @@ make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is
 static MonoClass *
 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
 {
-       int n = mono_generic_param_num (param);
+       int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
        MonoImage *image = param->image;
        GHashTable *ht;
 
@@ -5757,7 +5771,7 @@ get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
 static void
 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
 {
-       int n = mono_generic_param_num (param);
+       int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
        MonoImage *image = param->image;
        GHashTable *ht;