[utils] Another try to fix the windows build.
[mono.git] / mono / metadata / class.c
index 6516e2366aa882be9841951d3842d73af288e681..041b9e3dcd61c72b0fd2bd820763b8f53c62e59c 100644 (file)
@@ -72,10 +72,6 @@ static guint32 mono_field_resolve_flags (MonoClassField *field);
 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
 
-
-void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
-
-
 /*
 We use gclass recording to allow recursive system f types to be referenced by a parent.
 
@@ -1082,10 +1078,8 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
                        iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
        }
 
-       mono_loader_lock ();
        cached = mono_method_inflated_lookup (iresult, FALSE);
        if (cached) {
-               mono_loader_unlock ();
                g_free (iresult);
                return (MonoMethod*)cached;
        }
@@ -1156,12 +1150,9 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
         * is_generic_method_definition().
         */
 
-       mono_method_inflated_lookup (iresult, TRUE);
-       mono_loader_unlock ();
-       return result;
+       return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
 
 fail:
-       mono_loader_unlock ();
        g_free (iresult);
        return NULL;
 }
@@ -1241,7 +1232,7 @@ mono_method_get_generic_container (MonoMethod *method)
  * mono_method_set_generic_container:
  *
  *   Sets the generic container of METHOD to CONTAINER.
- * LOCKING: Acquires the loader lock.
+ * LOCKING: Acquires the image lock.
  */
 void
 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
@@ -1568,8 +1559,8 @@ mono_class_setup_fields (MonoClass *class)
        explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
 
        if (explicit_size) {
-               if ((packing_size & 0xfffffff0) != 0) {
-                       char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
+               if ((packing_size & 0xffffff00) != 0) {
+                       char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
                        mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
                        return;
                }
@@ -1946,7 +1937,6 @@ mono_class_layout_fields (MonoClass *class)
        case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
                guint8 *ref_bitmap;
 
-               ref_bitmap = g_new0 (guint8, class->instance_size / sizeof (gpointer));
                real_size = 0;
                for (i = 0; i < top; i++) {
                        gint32 align;
@@ -1981,7 +1971,6 @@ mono_class_layout_fields (MonoClass *class)
                                if (field->offset % sizeof (gpointer)) {
                                        mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
                                }
-                               ref_bitmap [field->offset / sizeof (gpointer)] = 1;
                        }
 
                        /*
@@ -1990,21 +1979,41 @@ mono_class_layout_fields (MonoClass *class)
                        real_size = MAX (real_size, size + field->offset);
                }
 
-               /* Check for overlapping reference and non-reference fields */
-               for (i = 0; i < top; i++) {
-                       field = &class->fields [i];
+               if (class->has_references) {
+                       ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
 
-                       if (mono_field_is_deleted (field))
-                               continue;
-                       if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
-                               continue;
+                       /* Check for overlapping reference and non-reference fields */
+                       for (i = 0; i < top; i++) {
+                               MonoType *ftype;
 
-                       if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
-                               char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset);
-                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
+                               field = &class->fields [i];
+
+                               if (mono_field_is_deleted (field))
+                                       continue;
+                               if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+                                       continue;
+                               ftype = mono_type_get_underlying_type (field->type);
+                               if (MONO_TYPE_IS_REFERENCE (ftype))
+                                       ref_bitmap [field->offset / sizeof (gpointer)] = 1;
                        }
+                       for (i = 0; i < top; i++) {
+                               field = &class->fields [i];
+
+                               if (mono_field_is_deleted (field))
+                                       continue;
+                               if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+                                       continue;
+
+                               // FIXME: Too much code does this
+#if 0
+                               if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
+                                       char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset);
+                                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
+                               }
+#endif
+                       }
+                       g_free (ref_bitmap);
                }
-               g_free (ref_bitmap);
 
                class->instance_size = MAX (real_size, class->instance_size);
                if (class->instance_size & (class->min_align - 1)) {
@@ -2139,12 +2148,18 @@ mono_class_setup_methods (MonoClass *class)
                MonoMethodSignature *sig;
                int count_generic = 0, first_generic = 0;
                int method_num = 0;
+               gboolean jagged_ctor = FALSE;
 
                count = 3 + (class->rank > 1? 2: 1);
 
                mono_class_setup_interfaces (class, &error);
                g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
 
+               if (class->rank == 1 && class->element_class->rank) {
+                       jagged_ctor = TRUE;
+                       class->method.count ++;
+               }
+
                if (class->interface_count) {
                        count_generic = generic_array_methods (class);
                        first_generic = count;
@@ -2173,6 +2188,19 @@ mono_class_setup_methods (MonoClass *class)
                        amethod = create_array_method (class, ".ctor", sig);
                        methods [method_num++] = amethod;
                }
+
+               if (jagged_ctor) {
+                       /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
+                       sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
+                       sig->ret = &mono_defaults.void_class->byval_arg;
+                       sig->pinvoke = TRUE;
+                       sig->hasthis = TRUE;
+                       for (i = 0; i < class->rank + 1; ++i)
+                               sig->params [i] = &mono_defaults.int32_class->byval_arg;
+                       amethod = create_array_method (class, ".ctor", sig);
+                       methods [method_num++] = amethod;
+               }
+
                /* element Get (idx11, [idx2, ...]) */
                sig = mono_metadata_signature_alloc (class->image, class->rank);
                sig->ret = &class->element_class->byval_arg;
@@ -5233,9 +5261,6 @@ mono_class_init (MonoClass *class)
 
        mono_loader_unlock ();
 
-       if (mono_debugger_class_init_func)
-               mono_debugger_class_init_func (class);
-
        return class->exception_type == MONO_EXCEPTION_NONE;
 }
 
@@ -6100,8 +6125,11 @@ make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is
 
 #define FAST_CACHE_SIZE 16
 
+/*
+ * LOCKING: Takes the image lock depending on @take_lock.
+ */
 static MonoClass *
-get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
+get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
 {
        int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
        MonoImage *image = param->image;
@@ -6115,26 +6143,33 @@ get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
                else
                        return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
        } else {
+               MonoClass *klass = NULL;
                ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
-               return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
+               if (ht) {
+                       if (take_lock)
+                               mono_image_lock (image);
+                       klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
+                       if (take_lock)
+                               mono_image_unlock (image);
+               }
+               return klass;
        }
 }
 
 /*
- * LOCKING: Acquires the loader lock.
+ * LOCKING: Image lock (param->image) must be held
  */
 static void
 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
 {
        int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
        MonoImage *image = param->image;
-       GHashTable *ht;
 
        g_assert (image);
 
        if (n < FAST_CACHE_SIZE) {
                if (is_mvar) {
-                       /* No locking needed */
+                       /* Requires locking to avoid droping an already published class */
                        if (!image->mvar_cache_fast)
                                image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
                        image->mvar_cache_fast [n] = klass;
@@ -6143,54 +6178,42 @@ set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *kla
                                image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
                        image->var_cache_fast [n] = klass;
                }
-               return;
-       }
-       ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
-       if (!ht) {
-               mono_image_lock (image);
-               ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
+       } else {
+               GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
                if (!ht) {
-                       ht = g_hash_table_new (NULL, NULL);
-                       mono_memory_barrier ();
-                       if (is_mvar)
-                               image->mvar_cache_slow = ht;
-                       else
-                               image->var_cache_slow = ht;
+                       ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
+                       if (!ht) {
+                               ht = g_hash_table_new (NULL, NULL);
+                               mono_memory_barrier ();
+                               if (is_mvar)
+                                       image->mvar_cache_slow = ht;
+                               else
+                                       image->var_cache_slow = ht;
+                       }
                }
-               mono_image_unlock (image);
+               g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
        }
-
-       g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
 }
 
 /*
- * LOCKING: Acquires the loader lock.
+ * LOCKING: Acquires the image lock (@image).
  */
 MonoClass *
 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
 {
        MonoGenericContainer *container = mono_generic_param_owner (param);
-       MonoGenericParamInfo *pinfo;
-       MonoClass *klass;
-
-       mono_loader_lock ();
+       MonoGenericParamInfo *pinfo = NULL;
+       MonoClass *klass, *klass2;
 
        if (container) {
                pinfo = mono_generic_param_info (param);
-               if (pinfo->pklass) {
-                       mono_loader_unlock ();
-                       return pinfo->pklass;
-               }
+               klass = pinfo->pklass;
        } else {
-               pinfo = NULL;
                image = NULL;
-
-               klass = get_anon_gparam_class (param, is_mvar);
-               if (klass) {
-                       mono_loader_unlock ();
-                       return klass;
-               }
+               klass = get_anon_gparam_class (param, is_mvar, TRUE);
        }
+       if (klass)
+               return klass;
 
        if (!image && container) {
                if (is_mvar) {
@@ -6208,15 +6231,30 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb
 
        mono_memory_barrier ();
 
+       if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
+               image = mono_defaults.corlib;
+
+       mono_image_lock (image);
        if (container)
-               pinfo->pklass = klass;
+               klass2 = pinfo->pklass;
        else
-               set_anon_gparam_class (param, is_mvar, klass);
+               klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
 
-       mono_loader_unlock ();
+       if (klass2) {
+               klass = klass2;
+       } else {
+               if (container)
+                       pinfo->pklass = klass;
+               else
+                       set_anon_gparam_class (param, is_mvar, klass);
+       }
+       mono_image_unlock (image);
 
        /* FIXME: Should this go inside 'make_generic_param_klass'? */
-       mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+       if (klass2)
+               mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
+       else
+               mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
 
        return klass;
 }
@@ -6232,15 +6270,15 @@ mono_ptr_class_get (MonoType *type)
        el_class = mono_class_from_mono_type (type);
        image = el_class->image;
 
-       mono_loader_lock ();
-
-       if (!image->ptr_cache)
-               image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
-
-       if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
-               mono_loader_unlock ();
-               return result;
+       mono_image_lock (image);
+       if (image->ptr_cache) {
+               if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
+                       mono_image_unlock (image);
+                       return result;
+               }
        }
+       mono_image_unlock (image);
+       
        result = mono_image_alloc0 (image, sizeof (MonoClass));
 
        classes_size += sizeof (MonoClass);
@@ -6267,9 +6305,19 @@ mono_ptr_class_get (MonoType *type)
 
        mono_class_setup_supertypes (result);
 
+       mono_image_lock (image);
+       if (image->ptr_cache) {
+               MonoClass *result2;
+               if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
+                       mono_image_unlock (image);
+                       mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
+                       return result2;
+               }
+       } else {
+               image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
+       }
        g_hash_table_insert (image->ptr_cache, el_class, result);
-
-       mono_loader_unlock ();
+       mono_image_unlock (image);
 
        mono_profiler_class_loaded (result, MONO_PROFILE_OK);
 
@@ -8437,11 +8485,16 @@ mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
                sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
                mono_metadata_decode_blob_size (sig, &sig);
                if (*sig == 0x6) { /* it's a field */
+                       MonoError error;
                        MonoClass *klass;
                        MonoClassField *field;
-                       field = mono_field_from_token (image, token, &klass, context);
+                       field = mono_field_from_token_checked (image, token, &klass, context, &error);
                        if (handle_class)
                                *handle_class = mono_defaults.fieldhandle_class;
+                       if (!field) {
+                               mono_loader_set_error_from_mono_error (&error);
+                               mono_error_cleanup (&error); /* FIXME Don't swallow the error */
+                       }
                        return field;
                } else {
                        MonoMethod *meth;