X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=da8fc30585b67fb1fa23f44a182cb0ae2ea3ce3f;hb=ac1d494270ac25b3fd885ef7d8b52cb27109861d;hp=6492fd6ca214bf232689e806cb2daac25bc5afb4;hpb=7b5ec9f82ca4b62b7e752552cd2dc5ecdcb34ae3;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 6492fd6ca21..da8fc30585b 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -56,9 +56,9 @@ gboolean mono_print_vtable = FALSE; gboolean mono_align_small_structs = FALSE; /* Statistics */ -guint32 inflated_classes_size, inflated_methods_size; -guint32 classes_size, class_ext_size, class_ext_count; -guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count; +gint32 inflated_classes_size, inflated_methods_size; +gint32 classes_size; +gint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count; /* Low level lock which protects data structures in this module */ static mono_mutex_t classes_mutex; @@ -1092,7 +1092,7 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k UnlockedIncrement (&mono_stats.inflated_method_count); - inflated_methods_size += sizeof (MonoMethodInflated); + UnlockedAdd (&inflated_methods_size, sizeof (MonoMethodInflated)); sig = mono_method_signature (method); if (!sig) { @@ -1513,6 +1513,7 @@ mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoCla * Sets the following fields in \p klass: * - all the fields initialized by mono_class_init_sizes () * - element_class/cast_class (for enums) + * - sizes:element_size (for arrays) * - field->type/offset for all fields * - fields_inited * @@ -1772,6 +1773,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ MonoClassField *field; gboolean blittable; int instance_size = base_instance_size; + int element_size = -1; int class_size, min_align; int *field_offsets; gboolean *fields_has_references; @@ -2101,6 +2103,9 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ else if (klass->byval_arg.type == MONO_TYPE_PTR) instance_size = sizeof (MonoObject) + sizeof (gpointer); + if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY) + element_size = mono_class_array_element_size (klass->element_class); + /* Publish the data */ mono_loader_lock (); if (klass->instance_size && !klass->image->dynamic) { @@ -2131,6 +2136,9 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ klass->fields [i].offset = field_offsets [i]; } + if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY) + klass->sizes.element_size = element_size; + mono_memory_barrier (); klass->size_inited = 1; mono_loader_unlock (); @@ -2918,6 +2926,10 @@ collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTabl *ifaces = g_hash_table_new (NULL, NULL); if (g_hash_table_lookup (*ifaces, ic)) continue; + /* A gparam is not an implemented interface for the purposes of + * mono_class_get_implemented_interfaces */ + if (mono_class_is_gparam (ic)) + continue; g_ptr_array_add (*res, ic); g_hash_table_insert (*ifaces, ic, ic); mono_class_init (ic); @@ -3308,7 +3320,9 @@ setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite) for (i = 0; i < k->interface_count; i++) { ic = k->interfaces [i]; - mono_class_init (ic); + /* A gparam does not have any interface_id set. */ + if (! mono_class_is_gparam (ic)) + mono_class_init (ic); if (max_iid < ic->interface_id) max_iid = ic->interface_id; @@ -4880,7 +4894,7 @@ mono_class_init (MonoClass *klass) GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id); if (g_slist_find (init_list, klass)) { mono_class_set_type_load_failure (klass, "Recursive type definition detected"); - goto leave; + goto leave_no_init_pending; } init_list = g_slist_prepend (init_list, klass); mono_native_tls_set_value (init_pending_tls_id, init_list); @@ -4941,12 +4955,19 @@ mono_class_init (MonoClass *klass) ghcimpl = cached_info.ghcimpl; has_cctor = cached_info.has_cctor; } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) { - /* SZARRAY can have 2 vtable layouts, with and without the stelemref method. + /* SZARRAY can have 3 vtable layouts, with and without the stelemref method and enum element type * The first slot if for array with. */ - static int szarray_vtable_size[2] = { 0 }; + static int szarray_vtable_size[3] = { 0 }; - int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1; + int slot; + + if (MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg)) + slot = 0; + else if (klass->element_class->enumtype) + slot = 1; + else + slot = 2; /* SZARRAY case */ if (!szarray_vtable_size [slot]) { @@ -5079,10 +5100,12 @@ mono_class_init (MonoClass *klass) goto leave; - leave: +leave: + init_list = mono_native_tls_get_value (init_pending_tls_id); init_list = g_slist_remove (init_list, klass); mono_native_tls_set_value (init_pending_tls_id, init_list); +leave_no_init_pending: if (locked) mono_loader_unlock (); @@ -5511,7 +5534,7 @@ mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char * Create the MonoClass* representing the specified type token. * \p type_token must be a TypeDef token. * - * FIXME: don't return NULL on failure, just the the caller figure it out. + * FIXME: don't return NULL on failure, just let the caller figure it out. */ static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error) @@ -5550,12 +5573,12 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError if (mono_metadata_has_generic_params (image, type_token)) { klass = mono_image_alloc0 (image, sizeof (MonoClassGtd)); klass->class_kind = MONO_CLASS_GTD; - classes_size += sizeof (MonoClassGtd); + UnlockedAdd (&classes_size, sizeof (MonoClassGtd)); ++class_gtd_count; } else { klass = mono_image_alloc0 (image, sizeof (MonoClassDef)); klass->class_kind = MONO_CLASS_DEF; - classes_size += sizeof (MonoClassDef); + UnlockedAdd (&classes_size, sizeof (MonoClassDef)); ++class_def_count; } @@ -5994,8 +6017,8 @@ make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo) klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam)); klass->class_kind = MONO_CLASS_GPARAM; - classes_size += sizeof (MonoClassGenericParam); - ++class_gparam_count; + UnlockedAdd (&classes_size, sizeof (MonoClassGenericParam)); + UnlockedIncrement (&class_gparam_count); if (pinfo) { CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name ); @@ -6274,7 +6297,7 @@ mono_ptr_class_get (MonoType *type) result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer)); - classes_size += sizeof (MonoClassPointer); + UnlockedAdd (&classes_size, sizeof (MonoClassPointer)); ++class_pointer_count; result->parent = NULL; /* no parent for PTR types */ @@ -6364,7 +6387,7 @@ mono_fnptr_class_get (MonoMethodSignature *sig) MONO_PROFILER_RAISE (class_loading, (result)); - classes_size += sizeof (MonoClassPointer); + UnlockedAdd (&classes_size, sizeof (MonoClassPointer)); ++class_pointer_count; g_hash_table_insert (ptr_hash, sig, result); @@ -6596,7 +6619,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) /* element_size -1 is ok as this is not an instantitable type*/ klass->sizes.element_size = -1; } else - klass->sizes.element_size = mono_class_array_element_size (eclass); + klass->sizes.element_size = -1; mono_class_setup_supertypes (klass); @@ -6692,7 +6715,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) MONO_PROFILER_RAISE (class_loading, (klass)); - classes_size += sizeof (MonoClassArray); + UnlockedAdd (&classes_size, sizeof (MonoClassArray)); ++class_array_count; if (rank == 1 && !bounded) { @@ -8210,22 +8233,31 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass) return mono_gparam_is_assignable_from (klass, oklass); } - if (MONO_CLASS_IS_INTERFACE (klass)) { - if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) { - MonoGenericParam *gparam = oklass->byval_arg.data.generic_param; - MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints; - int i; + /* This can happen if oklass is a tyvar that has a constraint which is another tyvar which in turn + * has a constraint which is a class type: + * + * class Foo { } + * class G where T1 : T2 where T2 : Foo { } + * + * In this case, Foo is assignable from T1. + */ + if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) { + MonoGenericParam *gparam = oklass->byval_arg.data.generic_param; + MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints; + int i; - if (constraints) { - for (i = 0; constraints [i]; ++i) { - if (mono_class_is_assignable_from (klass, constraints [i])) - return TRUE; - } + if (constraints) { + for (i = 0; constraints [i]; ++i) { + if (mono_class_is_assignable_from (klass, constraints [i])) + return TRUE; } - - return FALSE; } + return mono_class_has_parent (oklass, klass); + } + + if (MONO_CLASS_IS_INTERFACE (klass)) { + /* interface_offsets might not be set for dynamic classes */ if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) { /* @@ -8634,11 +8666,16 @@ handle_enum: * \param ac pointer to a \c MonoArrayClass * * \returns The size of single array element. + * + * LOCKING: Acquires the loader lock. */ gint32 mono_array_element_size (MonoClass *ac) { g_assert (ac->rank); + if (G_UNLIKELY (!ac->size_inited)) { + mono_class_setup_fields (ac); + } return ac->sizes.element_size; } @@ -9893,7 +9930,9 @@ mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...) * mono_classes_init: * * Initialize the resources used by this module. + * Known racy counters: `class_gparam_count`, `classes_size` and `inflated_methods_size` */ +MONO_NO_SANITIZE_THREAD void mono_classes_init (void) { @@ -10508,8 +10547,8 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error) if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) { MonoType *args [1]; - /* generic IList, ICollection, IEnumerable */ - interface_count = 2; + /* IList and IReadOnlyList -> 2x if enum*/ + interface_count = klass->element_class->enumtype ? 4 : 2; interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count); args [0] = &klass->element_class->byval_arg; @@ -10517,6 +10556,13 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error) mono_defaults.generic_ilist_class, 1, args, FALSE); interfaces [1] = mono_class_bind_generic_parameters ( mono_defaults.generic_ireadonlylist_class, 1, args, FALSE); + if (klass->element_class->enumtype) { + args [0] = mono_class_enum_basetype (klass->element_class); + interfaces [2] = mono_class_bind_generic_parameters ( + mono_defaults.generic_ilist_class, 1, args, FALSE); + interfaces [3] = mono_class_bind_generic_parameters ( + mono_defaults.generic_ireadonlylist_class, 1, args, FALSE); + } } else if (mono_class_is_ginst (klass)) { MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;