X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=041b9e3dcd61c72b0fd2bd820763b8f53c62e59c;hb=dd07fe7aaf26f0ecac3fe846218b6f960c7cbf9e;hp=6516e2366aa882be9841951d3842d73af288e681;hpb=8d9f05ea9a943ff1a36bb0ef3dd0521853d3a489;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 6516e2366aa..041b9e3dcd6 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -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;