X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=9c72644a3775b529adcdf7edb369a70f71ce5788;hb=de3b35df91b2665577a649c8320cd97791045e46;hp=fe08d0e52b640d3fe21aa85b74eeb5017cb720a4;hpb=7d40fd72f65b952d492bcd2fd45f95e0569a48d3;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index fe08d0e52b6..9c72644a377 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -111,6 +111,8 @@ typedef gboolean (*gclass_record_func) (MonoClass*, void*); /* This TLS variable points to a GSList of classes which have setup_fields () executing */ static MonoNativeTlsKey setup_fields_tls_id; +static MonoNativeTlsKey init_pending_tls_id; + static inline void classes_lock (void) { @@ -504,8 +506,8 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, } if (is_recursed) break; - if (klass->generic_class) { - MonoGenericClass *gclass = klass->generic_class; + if (mono_class_is_ginst (klass)) { + MonoGenericClass *gclass = mono_class_get_generic_class (klass); MonoGenericInst *inst = gclass->context.class_inst; MonoTypeNameFormat nested_format; int i; @@ -825,7 +827,8 @@ mono_generic_class_get_context (MonoGenericClass *gclass) MonoGenericContext * mono_class_get_context (MonoClass *klass) { - return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL; + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); + return gklass ? mono_generic_class_get_context (gklass) : NULL; } /* @@ -836,24 +839,11 @@ mono_class_get_context (MonoClass *klass) MonoGenericContainer* mono_class_get_generic_container (MonoClass *klass) { - g_assert (klass->is_generic); + g_assert (mono_class_is_gtd (klass)); return klass->generic_container; } -/* - * mono_class_get_generic_class: - * - * Return the MonoGenericClass of KLASS, which should be a generic instance. - */ -MonoGenericClass* -mono_class_get_generic_class (MonoClass *klass) -{ - g_assert (klass->is_inflated); - - return klass->generic_class; -} - /* * mono_class_inflate_generic_type_with_mempool: * @mempool: a mempool @@ -1093,14 +1083,12 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst; if (!context->class_inst) { - g_assert (!iresult->declaring->klass->generic_class); + g_assert (!mono_class_is_ginst (iresult->declaring->klass)); if (iresult->declaring->klass->generic_container) iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst; - else if (iresult->declaring->klass->generic_class) - iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst; } /* This can happen with some callers like mono_object_get_virtual_method () */ - if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class) + if (!iresult->declaring->klass->generic_container && !mono_class_is_ginst (iresult->declaring->klass)) iresult->context.class_inst = NULL; MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult); @@ -1158,10 +1146,11 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k } } - if (!klass_hint || !klass_hint->generic_class || - klass_hint->generic_class->container_class != method->klass || - klass_hint->generic_class->context.class_inst != context->class_inst) - klass_hint = NULL; + if (klass_hint) { + MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint); + if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst)) + klass_hint = NULL; + } if (method->klass->generic_container) result->klass = klass_hint; @@ -1312,8 +1301,8 @@ mono_class_find_enum_basetype (MonoClass *klass, MonoError *error) if (klass->generic_container) container = klass->generic_container; - else if (klass->generic_class) { - MonoClass *gklass = klass->generic_class->container_class; + else if (mono_class_is_ginst (klass)) { + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; container = gklass->generic_container; g_assert (container); @@ -1351,7 +1340,7 @@ mono_class_find_enum_basetype (MonoClass *klass, MonoError *error) if (!ftype) goto fail; - if (klass->generic_class) { + if (mono_class_is_ginst (klass)) { //FIXME do we leak here? ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error); if (!mono_error_ok (error)) @@ -1405,8 +1394,9 @@ mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass) gpointer mono_class_alloc (MonoClass *klass, int size) { - if (klass->generic_class) - return mono_image_set_alloc (klass->generic_class->owner, size); + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); + if (gklass) + return mono_image_set_alloc (gklass->owner, size); else return mono_image_alloc (klass->image, size); } @@ -1437,6 +1427,7 @@ mono_class_alloc0 (MonoClass *klass, int size) static void mono_class_setup_basic_field_info (MonoClass *klass) { + MonoGenericClass *gklass; MonoClassField *field; MonoClassField *fields; MonoClass *gtd; @@ -1446,10 +1437,12 @@ mono_class_setup_basic_field_info (MonoClass *klass) if (klass->fields) return; - gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL; + gklass = mono_class_try_get_generic_class (klass); + gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL; image = klass->image; - if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) { + + if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) { /* * This happens when a generic instance of an unfinished generic typebuilder * is used as an element type for creating an array type. We can't initialize @@ -1532,15 +1525,9 @@ mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoCla * Initializes klass->fields, computes class layout and sizes. * typebuilder_setup_fields () is the corresponding function for dynamic classes. * Sets the following fields in @klass: - * - packing_size - * - min_align - * - blittable - * - has_references (if the class contains instance references firled or structs that contain references) - * - has_static_refs (same, but for static fields) - * - instance_size (size of the object in memory) - * - class_size (size needed for the static fields) - * - size_inited (flag set when the instance_size is set) + * - all the fields initialized by mono_class_init_sizes () * - element_class/cast_class (for enums) + * - field->type/offset for all fields * - fields_inited * * LOCKING: Acquires the loader lock. @@ -1558,12 +1545,14 @@ mono_class_setup_fields (MonoClass *klass) int instance_size; gboolean explicit_size; MonoClassField *field; - MonoClass *gtd; + MonoGenericContainer *container = NULL; + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); + MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL; if (klass->fields_inited) return; - if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) { + if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) { /* * This happens when a generic instance of an unfinished generic typebuilder * is used as an element type for creating an array type. We can't initialize @@ -1669,23 +1658,51 @@ mono_class_setup_fields (MonoClass *klass) mono_native_tls_set_value (setup_fields_tls_id, init_list); } +static void +init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info) +{ + if (cached_info) { + klass->instance_size = cached_info->instance_size; + klass->sizes.class_size = cached_info->class_size; + klass->packing_size = cached_info->packing_size; + klass->min_align = cached_info->min_align; + klass->blittable = cached_info->blittable; + klass->has_references = cached_info->has_references; + klass->has_static_refs = cached_info->has_static_refs; + klass->no_special_static_fields = cached_info->no_special_static_fields; + } + else { + if (!klass->size_inited) + mono_class_setup_fields (klass); + } +} /* - * mono_class_has_references: + + * mono_class_init_sizes: + * + * Initializes the size related fields of @klass without loading all field data if possible. + * Sets the following fields in @klass: + * - instance_size + * - sizes.class_size + * - packing_size + * - min_align + * - blittable + * - has_references + * - has_static_refs + * - size_inited + * Can fail the class. * - * Returns whenever @klass->has_references is set, initializing it if needed. - * Aquires the loader lock. + * LOCKING: Acquires the loader lock. */ -static gboolean -mono_class_has_references (MonoClass *klass) +static void +mono_class_init_sizes (MonoClass *klass) { - if (klass->init_pending) { - /* Be conservative */ - return TRUE; - } else { - mono_class_init (klass); + MonoCachedClassInfo cached_info; + gboolean has_cached_info; - return klass->has_references; - } + has_cached_info = mono_class_get_cached_class_info (klass, &cached_info); + + init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL); } /* @@ -1705,16 +1722,29 @@ mono_type_get_basic_type_from_generic (MonoType *type) return type; } +static gboolean +class_has_references (MonoClass *klass) +{ + mono_class_init_sizes (klass); + + /* + * has_references is not set if this is called recursively, but this is not a problem since this is only used + * during field layout, and instance fields are initialized before static fields, and instance fields can't + * embed themselves. + */ + return klass->has_references; +} + 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))))) + if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && 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 class_has_references (mono_class_from_mono_type (gparam->gshared_constraint)); } return FALSE; } @@ -2205,9 +2235,9 @@ mono_class_setup_methods (MonoClass *klass) if (klass->methods) return; - if (klass->generic_class) { + if (mono_class_is_ginst (klass)) { MonoError error; - MonoClass *gklass = klass->generic_class->container_class; + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; mono_class_init (gklass); if (!mono_class_has_failure (gklass)) @@ -2370,13 +2400,14 @@ MonoMethod* mono_class_get_method_by_index (MonoClass *klass, int index) { MonoError error; + + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); /* Avoid calling setup_methods () if possible */ - if (klass->generic_class && !klass->methods) { - MonoClass *gklass = klass->generic_class->container_class; + if (gklass && !klass->methods) { MonoMethod *m; m = mono_class_inflate_generic_method_full_checked ( - gklass->methods [index], klass, mono_class_get_context (klass), &error); + gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error); g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */ /* * If setup_methods () is called later for this class, no duplicates are created, @@ -2406,7 +2437,7 @@ mono_class_get_method_by_index (MonoClass *klass, int index) MonoMethod* mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method) { - MonoClass *gklass = klass->generic_class->container_class; + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; int i; g_assert (method->klass == gklass); @@ -2451,9 +2482,9 @@ mono_class_get_vtable_entry (MonoClass *klass, int offset) return klass->parent->vtable [offset]; } - if (klass->generic_class) { + if (mono_class_is_ginst (klass)) { MonoError error; - MonoClass *gklass = klass->generic_class->container_class; + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; mono_class_setup_vtable (gklass); m = gklass->vtable [offset]; @@ -2502,8 +2533,8 @@ mono_class_setup_properties (MonoClass *klass) if (klass->ext && klass->ext->properties) return; - if (klass->generic_class) { - MonoClass *gklass = klass->generic_class->container_class; + if (mono_class_is_ginst (klass)) { + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; mono_class_init (gklass); mono_class_setup_properties (gklass); @@ -2633,8 +2664,8 @@ mono_class_setup_events (MonoClass *klass) if (klass->ext && klass->ext->events) return; - if (klass->generic_class) { - MonoClass *gklass = klass->generic_class->container_class; + if (mono_class_is_ginst (klass)) { + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; MonoGenericContext *context = NULL; mono_class_setup_events (gklass); @@ -2824,7 +2855,7 @@ mono_get_unique_iid (MonoClass *klass) } mono_bitset_set (global_interface_bitset, iid); /* set the bit also in the per-image set */ - if (!klass->generic_class) { + if (!mono_class_is_ginst (klass)) { if (klass->image->interface_bitset) { if (iid >= mono_bitset_size (klass->image->interface_bitset)) { MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1); @@ -2843,8 +2874,9 @@ mono_get_unique_iid (MonoClass *klass) if (mono_print_vtable) { int generic_id; char *type_name = mono_type_full_name (&klass->byval_arg); - if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) { - generic_id = klass->generic_class->context.class_inst->id; + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); + if (gklass && !gklass->context.class_inst->is_open) { + generic_id = gklass->context.class_inst->id; g_assert (generic_id != 0); } else { generic_id = 0; @@ -3057,6 +3089,12 @@ fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *ecla valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass)); } +static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1) +static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1) +static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1) +static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1) +static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1) + /* this won't be needed once bug #325495 is completely fixed * though we'll need something similar to know which interfaces to allow * in arrays when they'll be lazyly created @@ -3074,11 +3112,11 @@ static MonoClass** get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator) { MonoClass *eclass = klass->element_class; - static MonoClass* generic_icollection_class = NULL; - static MonoClass* generic_ienumerable_class = NULL; - static MonoClass* generic_ienumerator_class = NULL; - static MonoClass* generic_ireadonlylist_class = NULL; - static MonoClass* generic_ireadonlycollection_class = NULL; + MonoClass* generic_icollection_class; + MonoClass* generic_ienumerable_class; + MonoClass* generic_ienumerator_class; + MonoClass* generic_ireadonlylist_class; + MonoClass* generic_ireadonlycollection_class; MonoClass *valuetype_types[2] = { NULL, NULL }; MonoClass **interfaces = NULL; int i, nifaces, interface_count, real_count, original_rank; @@ -3094,11 +3132,12 @@ get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enume eclass_is_valuetype = FALSE; original_rank = eclass->rank; if (klass->byval_arg.type != MONO_TYPE_SZARRAY) { - if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) { + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); + if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) { /* * For a Enumerator we need to get the list of interfaces for T. */ - eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]); + eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]); original_rank = eclass->rank; if (!eclass->rank) eclass = eclass->element_class; @@ -3116,18 +3155,11 @@ get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enume */ all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE; - if (!generic_icollection_class) { - generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib, - "System.Collections.Generic", "ICollection`1"); - generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib, - "System.Collections.Generic", "IEnumerable`1"); - generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib, - "System.Collections.Generic", "IEnumerator`1"); - generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib, - "System.Collections.Generic", "IReadOnlyList`1"); - generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib, - "System.Collections.Generic", "IReadOnlyCollection`1"); - } + generic_icollection_class = mono_class_get_generic_icollection_class (); + generic_ienumerable_class = mono_class_get_generic_ienumerable_class (); + generic_ienumerator_class = mono_class_get_generic_ienumerator_class (); + generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class (); + generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class (); mono_class_init (eclass); @@ -3493,8 +3525,8 @@ mono_class_interface_match (const uint8_t *bitmap, int id) #endif /* - * LOCKING: this is supposed to be called with the loader lock held. * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details. + * LOCKING: Acquires the loader lock. */ static int setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite) @@ -3529,8 +3561,7 @@ setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite) for (i = 0; i < k->interface_count; i++) { ic = k->interfaces [i]; - if (!ic->inited) - mono_class_init (ic); + mono_class_init (ic); if (max_iid < ic->interface_id) max_iid = ic->interface_id; @@ -3567,14 +3598,13 @@ setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite) if (max_iid < klass->interface_id) max_iid = klass->interface_id; } - klass->max_interface_id = max_iid; + /* compute vtable offset for interfaces */ interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces); interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces); - for (i = 0; i < num_ifaces; i++) { + for (i = 0; i < num_ifaces; i++) interface_offsets_full [i] = -1; - } /* skip the current class */ for (j = 0; j < klass->idepth - 1; j++) { @@ -3648,7 +3678,7 @@ setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite) for (i = 0; i < num_array_interfaces; ++i) { int offset; ic = array_interfaces [i]; - if (ic->generic_class->container_class == mono_defaults.generic_ilist_class) + if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class) offset = ilist_offset; else if (strcmp (ic->name, "ICollection`1") == 0) offset = icollection_offset; @@ -3667,11 +3697,14 @@ setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite) } for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) { - if (interface_offsets_full [i] != -1) { + if (interface_offsets_full [i] != -1) interface_offsets_count ++; - } } + /* Publish the data */ + mono_loader_lock (); + + klass->max_interface_id = max_iid; /* * We might get called multiple times: * - mono_class_init () @@ -3712,6 +3745,7 @@ setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite) klass->interface_bitmap = bitmap; #endif } + mono_loader_unlock (); end: g_free (interfaces_full); @@ -3726,7 +3760,7 @@ end: //printf ("JUST DONE: "); //print_implemented_interfaces (klass); - + return cur_slot; } @@ -3744,11 +3778,7 @@ end: void mono_class_setup_interface_offsets (MonoClass *klass) { - mono_loader_lock (); - setup_interface_offsets (klass, 0, FALSE); - - mono_loader_unlock (); } /*Checks if @klass has @parent as one of it's parents type gtd @@ -3775,16 +3805,17 @@ mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup) { MonoGenericInst *ginst; int i; - if (!klass->generic_class) { + + if (!mono_class_is_ginst (klass)) { mono_class_setup_vtable_full (klass, in_setup); return !mono_class_has_failure (klass); } mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup); - if (mono_class_set_type_load_failure_causedby_class (klass, klass->generic_class->container_class, "Failed to load generic definition vtable")) + if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable")) return FALSE; - ginst = klass->generic_class->context.class_inst; + ginst = mono_class_get_generic_class (klass)->context.class_inst; for (i = 0; i < ginst->type_argc; ++i) { MonoClass *arg; if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST) @@ -3855,7 +3886,7 @@ mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup) mono_stats.generic_vtable_count ++; in_setup = g_list_prepend (in_setup, klass); - if (klass->generic_class) { + if (mono_class_is_ginst (klass)) { if (!mono_class_check_vtable_constraints (klass, in_setup)) { mono_loader_unlock (); g_list_remove (in_setup, klass); @@ -3863,7 +3894,7 @@ mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup) } context = mono_class_get_context (klass); - type_token = klass->generic_class->container_class->type_token; + type_token = mono_class_get_generic_class (klass)->container_class->type_token; } else { context = (MonoGenericContext *) klass->generic_container; type_token = klass->type_token; @@ -4393,9 +4424,9 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot); /* Optimized version for generic instances */ - if (klass->generic_class) { + if (mono_class_is_ginst (klass)) { MonoError error; - MonoClass *gklass = klass->generic_class->container_class; + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; MonoMethod **tmp; mono_class_setup_vtable_full (gklass, in_setup); @@ -4769,8 +4800,8 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o } } - if (klass->generic_class) { - MonoClass *gklass = klass->generic_class->container_class; + if (mono_class_is_ginst (klass)) { + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; mono_class_init (gklass); @@ -4873,14 +4904,14 @@ mono_method_get_vtable_slot (MonoMethod *method) MonoClass *gklass; int i; - if (!method->klass->generic_class) { + if (!mono_class_is_ginst (method->klass)) { 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; + g_assert (mono_class_is_ginst (method->klass)); + gklass = mono_class_get_generic_class (method->klass)->container_class; mono_class_setup_methods (method->klass); g_assert (method->klass->methods); for (i = 0; i < method->klass->method.count; ++i) { @@ -5021,7 +5052,7 @@ setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **met int i; tmp_context.class_inst = NULL; - tmp_context.method_inst = iface->generic_class->context.class_inst; + tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst; //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0)); for (i = 0; i < generic_array_method_num; i++) { @@ -5051,21 +5082,30 @@ concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2) /** * mono_class_init: - * @class: the class to initialize + * @klass: the class to initialize * * Compute the instance_size, class_size and other infos that cannot be * computed at mono_class_get() time. Also compute vtable_size if possible. * Returns TRUE on success or FALSE if there was a problem in loading - * the type (incorrect assemblies, missing assemblies, methods, etc). + * the type (incorrect assemblies, missing assemblies, methods, etc). + * Initializes the following fields in @klass: + * - all the fields initialized by mono_class_init_sizes () + * - has_cctor + * - ghcimpl + * - inited * * LOCKING: Acquires the loader lock. */ gboolean mono_class_init (MonoClass *klass) { - int i; + int i, vtable_size = 0, array_method_count = 0; MonoCachedClassInfo cached_info; gboolean has_cached_info; + gboolean locked = FALSE; + gboolean ghcimpl = FALSE; + gboolean has_cctor = FALSE; + int first_iface_slot = 0; g_assert (klass); @@ -5075,28 +5115,27 @@ mono_class_init (MonoClass *klass) /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/ - /* We do everything inside the lock to prevent races */ - mono_loader_lock (); - - if (klass->inited || mono_class_has_failure (klass)) { - mono_loader_unlock (); - /* Somebody might have gotten in before us */ - return !mono_class_has_failure (klass); - } - - if (klass->init_pending) { + /* + * This function can recursively call itself. + */ + 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; } + init_list = g_slist_prepend (init_list, klass); + mono_native_tls_set_value (init_pending_tls_id, init_list); - klass->init_pending = 1; + /* + * We want to avoid doing complicated work inside locks, so we compute all the required + * information and write it to @klass inside a lock. + */ if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) { mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name)); goto leave; } - if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) { MonoClass *element_class = klass->element_class; if (!element_class->inited) @@ -5107,23 +5146,14 @@ mono_class_init (MonoClass *klass) mono_stats.initialized_class_count++; - if (klass->generic_class && !klass->generic_class->is_dynamic) { - MonoClass *gklass = klass->generic_class->container_class; - - mono_stats.generic_class_count++; - - klass->method = gklass->method; - klass->field = gklass->field; + if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) { + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; mono_class_init (gklass); - // FIXME: Why is this needed ? - if (!mono_class_has_failure (gklass)) - mono_class_setup_methods (gklass); if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init")) goto leave; - if (MONO_CLASS_IS_INTERFACE (klass)) - klass->interface_id = mono_get_unique_iid (klass); + mono_class_setup_interface_id (klass); } if (klass->parent && !klass->parent->inited) @@ -5131,38 +5161,10 @@ mono_class_init (MonoClass *klass) has_cached_info = mono_class_get_cached_class_info (klass, &cached_info); - if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes)) - klass->nested_classes_inited = TRUE; - - /* - * Computes the size used by the fields, and their locations - */ - if (has_cached_info) { - klass->instance_size = cached_info.instance_size; - klass->sizes.class_size = cached_info.class_size; - klass->packing_size = cached_info.packing_size; - klass->min_align = cached_info.min_align; - klass->blittable = cached_info.blittable; - klass->has_references = cached_info.has_references; - klass->has_static_refs = cached_info.has_static_refs; - klass->no_special_static_fields = cached_info.no_special_static_fields; - } - else - if (!klass->size_inited){ - mono_class_setup_fields (klass); - if (mono_class_has_failure (klass)) - goto leave; - } - - /* Initialize arrays */ - if (klass->rank) { - klass->method.count = 3 + (klass->rank > 1? 2: 1); - - if (klass->interface_count) { - int count_generic = generic_array_methods (klass); - klass->method.count += klass->interface_count * count_generic; - } - } + /* Compute instance size etc. */ + init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL); + if (mono_class_has_failure (klass)) + goto leave; mono_class_setup_supertypes (klass); @@ -5176,11 +5178,9 @@ mono_class_init (MonoClass *klass) */ if (has_cached_info) { /* AOT case */ - klass->vtable_size = cached_info.vtable_size; - klass->has_finalize = cached_info.has_finalize; - klass->has_finalize_inited = TRUE; - klass->ghcimpl = cached_info.ghcimpl; - klass->has_cctor = cached_info.has_cctor; + vtable_size = cached_info.vtable_size; + 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. * The first slot if for array with. @@ -5193,21 +5193,22 @@ mono_class_init (MonoClass *klass) if (!szarray_vtable_size [slot]) { mono_class_setup_vtable (klass); szarray_vtable_size [slot] = klass->vtable_size; + vtable_size = klass->vtable_size; } else { - klass->vtable_size = szarray_vtable_size[slot]; + vtable_size = szarray_vtable_size[slot]; } - } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) { - MonoClass *gklass = klass->generic_class->container_class; + } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) { + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; /* Generic instance case */ - klass->ghcimpl = gklass->ghcimpl; - klass->has_cctor = gklass->has_cctor; + ghcimpl = gklass->ghcimpl; + has_cctor = gklass->has_cctor; mono_class_setup_vtable (gklass); if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init")) goto leave; - klass->vtable_size = gklass->vtable_size; + vtable_size = gklass->vtable_size; } else { /* General case */ @@ -5231,7 +5232,7 @@ mono_class_init (MonoClass *klass) cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME); /* The find_method function ignores the 'flags' argument */ if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME)) - klass->has_cctor = 1; + has_cctor = 1; } else { mono_class_setup_methods (klass); if (mono_class_has_failure (klass)) @@ -5241,7 +5242,7 @@ mono_class_init (MonoClass *klass) MonoMethod *method = klass->methods [i]; if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && (strcmp (".cctor", method->name) == 0)) { - klass->has_cctor = 1; + has_cctor = 1; break; } } @@ -5249,45 +5250,85 @@ mono_class_init (MonoClass *klass) } } - if (klass->parent) { - MonoError parent_error; - mono_error_init (&parent_error); - int first_iface_slot; - /* This will compute klass->parent->vtable_size for some classes */ - mono_class_init (klass->parent); - if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to initialize")) { - goto leave; + if (klass->rank) { + array_method_count = 3 + (klass->rank > 1? 2: 1); + + if (klass->interface_count) { + int count_generic = generic_array_methods (klass); + array_method_count += klass->interface_count * count_generic; } - if (!klass->parent->vtable_size) { - /* FIXME: Get rid of this somehow */ + } + + if (klass->parent) { + if (!klass->parent->vtable_size) mono_class_setup_vtable (klass->parent); - if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize")) { - goto leave; - } - } + if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize")) + goto leave; + g_assert (klass->parent->vtable_size); first_iface_slot = klass->parent->vtable_size; if (mono_class_need_stelemref_method (klass)) ++first_iface_slot; - setup_interface_offsets (klass, first_iface_slot, TRUE); - } else { - setup_interface_offsets (klass, 0, TRUE); } + /* + * Do the actual changes to @klass inside the loader lock + */ + mono_loader_lock (); + locked = TRUE; + + if (klass->inited || mono_class_has_failure (klass)) { + mono_loader_unlock (); + /* Somebody might have gotten in before us */ + return !mono_class_has_failure (klass); + } + + mono_stats.initialized_class_count++; + + if (klass->generic_class && !klass->generic_class->is_dynamic) { + MonoClass *gklass = klass->generic_class->container_class; + + mono_stats.generic_class_count++; + + klass->method = gklass->method; + klass->field = gklass->field; + } + + if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes)) + klass->nested_classes_inited = TRUE; + klass->ghcimpl = ghcimpl; + klass->has_cctor = has_cctor; + if (vtable_size) + klass->vtable_size = vtable_size; + if (has_cached_info) { + klass->has_finalize = cached_info.has_finalize; + klass->has_finalize_inited = TRUE; + } + if (klass->rank) + klass->method.count = array_method_count; + + mono_loader_unlock (); + locked = FALSE; + + setup_interface_offsets (klass, first_iface_slot, TRUE); + if (mono_security_core_clr_enabled ()) mono_security_core_clr_check_inheritance (klass); - if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) + if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass)) mono_class_set_type_load_failure (klass, "Invalid generic instantiation"); goto leave; leave: + init_list = g_slist_remove (init_list, klass); + mono_native_tls_set_value (init_pending_tls_id, init_list); + /* Because of the double-checking locking pattern */ mono_memory_barrier (); klass->inited = 1; - klass->init_pending = 0; - mono_loader_unlock (); + if (locked) + mono_loader_unlock (); return !mono_class_has_failure (klass); } @@ -5311,8 +5352,8 @@ mono_class_has_finalizer (MonoClass *klass) MonoMethod *cmethod = NULL; if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) { - } else if (klass->generic_class) { - MonoClass *gklass = klass->generic_class->container_class; + } else if (mono_class_is_ginst (klass)) { + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; has_finalize = mono_class_has_finalizer (gklass); } else if (klass->parent && klass->parent->has_finalize) { @@ -5489,7 +5530,6 @@ mono_class_setup_mono_type (MonoClass *klass) if (MONO_CLASS_IS_INTERFACE (klass)) klass->interface_id = mono_get_unique_iid (klass); - } #ifndef DISABLE_COM @@ -5554,11 +5594,12 @@ mono_class_setup_parent (MonoClass *klass, MonoClass *parent) /* set the parent to something useful and safe, but mark the type as broken */ parent = mono_defaults.object_class; mono_class_set_type_load_failure (klass, ""); + g_assert (parent); } klass->parent = parent; - if (parent->generic_class && !parent->name) { + if (mono_class_is_ginst (parent) && !parent->name) { /* * If the parent is a generic instance, we may get * called before it is fully initialized, especially @@ -5658,7 +5699,7 @@ fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data) { MonoClass *gtd = (MonoClass*)user_data; /* Only try to fix generic instances of @gtd */ - if (gclass->generic_class->container_class != gtd) + if (mono_class_get_generic_class (gclass)->container_class != gtd) return FALSE; /* Check if the generic instance has no parent. */ @@ -5720,7 +5761,15 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]); nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]); - klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass)); + 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); + } else { + klass = mono_image_alloc0 (image, sizeof (MonoClassDef)); + klass->class_kind = MONO_CLASS_DEF; + classes_size += sizeof (MonoClassDef); + } klass->name = name; klass->name_space = nspace; @@ -5733,14 +5782,11 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass); - classes_size += sizeof (MonoClass); - /* * Check whether we're a generic type definition. */ klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL); if (klass->generic_container) { - klass->is_generic = 1; klass->generic_container->owner.klass = klass; klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous context = &klass->generic_container->context; @@ -5775,7 +5821,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent"); goto parent_failure; } - if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) { + if (klass->generic_container && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) { mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type"); goto parent_failure; } @@ -5911,8 +5957,8 @@ parent_failure: gboolean mono_class_is_nullable (MonoClass *klass) { - return klass->generic_class != NULL && - klass->generic_class->container_class == mono_defaults.generic_nullable_class; + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); + return gklass && gklass->container_class == mono_defaults.generic_nullable_class; } @@ -5921,7 +5967,7 @@ MonoClass* mono_class_get_nullable_param (MonoClass *klass) { g_assert (mono_class_is_nullable (klass)); - return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]); + return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]); } static void @@ -5929,7 +5975,7 @@ mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd) { if (gtd->parent) { MonoError error; - MonoGenericClass *gclass = klass->generic_class; + MonoGenericClass *gclass = mono_class_get_generic_class (klass); klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error); if (!mono_error_ok (&error)) { @@ -5967,7 +6013,7 @@ mono_generic_class_get_class (MonoGenericClass *gclass) return gclass->cached_class; } - klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass)); + klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst)); gklass = gclass->container_class; @@ -5989,8 +6035,9 @@ mono_generic_class_get_class (MonoGenericClass *gclass) klass->type_token = gklass->type_token; klass->field.count = gklass->field.count; - klass->is_inflated = 1; - klass->generic_class = gclass; + klass->class_kind = MONO_CLASS_GINST; + //FIXME add setter + ((MonoClassGenericInst*)klass)->generic_class = gclass; klass->byval_arg.type = MONO_TYPE_GENERICINST; klass->this_arg.type = klass->byval_arg.type; @@ -6041,7 +6088,7 @@ mono_generic_class_get_class (MonoGenericClass *gclass) mono_profiler_class_loaded (klass, MONO_PROFILE_OK); inflated_classes ++; - inflated_classes_size += sizeof (MonoClass); + inflated_classes_size += sizeof (MonoClassGenericInst); mono_loader_unlock (); @@ -6102,8 +6149,9 @@ make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo) gboolean is_mvar = container->is_method; gboolean is_anonymous = container->is_anonymous; - klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass)); - classes_size += sizeof (MonoClass); + klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam)); + klass->class_kind = MONO_CLASS_GPARAM; + classes_size += sizeof (MonoClassGenericParam); if (pinfo) { CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name ); @@ -6379,14 +6427,15 @@ mono_ptr_class_get (MonoType *type) } mono_image_unlock (image); - result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass)); + result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer)); - classes_size += sizeof (MonoClass); + classes_size += sizeof (MonoClassPointer); result->parent = NULL; /* no parent for PTR types */ result->name_space = el_class->name_space; name = g_strdup_printf ("%s*", el_class->name); result->name = mono_image_strdup (image, name); + result->class_kind = MONO_CLASS_POINTER; g_free (name); mono_profiler_class_event (result, MONO_PROFILE_START_LOAD); @@ -6446,6 +6495,7 @@ mono_fnptr_class_get (MonoMethodSignature *sig) result->parent = NULL; /* no parent for PTR types */ result->name_space = "System"; result->name = "MonoFNPtrFakeClass"; + result->class_kind = MONO_CLASS_POINTER; mono_profiler_class_event (result, MONO_PROFILE_START_LOAD); @@ -6658,10 +6708,12 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) if (!parent->inited) mono_class_init (parent); - klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass)); + klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray)); klass->image = image; klass->name_space = eclass->name_space; + klass->class_kind = MONO_CLASS_ARRAY; + nsize = strlen (eclass->name); name = (char *)g_malloc (nsize + 2 + rank + 1); memcpy (name, eclass->name, nsize); @@ -6677,7 +6729,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD); - classes_size += sizeof (MonoClass); + classes_size += sizeof (MonoClassArray); klass->type_token = 0; /* all arrays are marked serializable and sealed, bug #42779 */ @@ -6704,10 +6756,9 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) mono_class_setup_supertypes (klass); - if (eclass->generic_class) + if (mono_class_is_ginst (eclass)) mono_class_init (eclass); - if (!eclass->size_inited) - mono_class_setup_fields (eclass); + mono_class_init_sizes (eclass); mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type"); /*FIXME we fail the array type, but we have to let other fields be set.*/ @@ -6812,7 +6863,7 @@ gint32 mono_class_instance_size (MonoClass *klass) { if (!klass->size_inited) - mono_class_init (klass); + mono_class_init_sizes (klass); return klass->instance_size; } @@ -6823,13 +6874,13 @@ mono_class_instance_size (MonoClass *klass) * * Use to get the computed minimum alignment requirements for the specified class. * - * Returns: minimm alignment requirements + * Returns: minimum alignment requirements */ gint32 mono_class_min_align (MonoClass *klass) { if (!klass->size_inited) - mono_class_init (klass); + mono_class_init_sizes (klass); return klass->min_align; } @@ -6844,7 +6895,7 @@ mono_class_min_align (MonoClass *klass) * Returns: the size of a value of kind @klass */ gint32 -mono_class_value_size (MonoClass *klass, guint32 *align) +mono_class_value_size (MonoClass *klass, guint32 *align) { gint32 size; @@ -6873,8 +6924,8 @@ mono_class_data_size (MonoClass *klass) if (!klass->inited) mono_class_init (klass); /* This can happen with dynamically created types */ - if (!klass->fields_inited) - mono_class_setup_fields (klass); + if (!klass->size_inited) + mono_class_init_sizes (klass); /* in arrays, sizes.class_size is unioned with element_size * and arrays have no static fields @@ -8063,10 +8114,10 @@ mono_class_has_variant_generic_params (MonoClass *klass) int i; MonoGenericContainer *container; - if (!klass->generic_class) + if (!mono_class_is_ginst (klass)) return FALSE; - container = klass->generic_class->container_class->generic_container; + container = mono_class_get_generic_class (klass)->container_class->generic_container; for (i = 0; i < container->type_argc; ++i) if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT)) @@ -8119,8 +8170,8 @@ mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd) return FALSE; - klass_argv = &klass->generic_class->context.class_inst->type_argv [0]; - oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0]; + klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]; + oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0]; for (j = 0; j < container->type_argc; ++j) { MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]); @@ -8381,8 +8432,8 @@ mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass) if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd) return FALSE; - klass_argv = &klass->generic_class->context.class_inst->type_argv [0]; - oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0]; + klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]; + oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0]; for (j = 0; j < container->type_argc; ++j) { MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]); @@ -8559,8 +8610,8 @@ mono_class_get_cctor (MonoClass *klass) return result; } - if (klass->generic_class && !klass->methods) - return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class)); + if (mono_class_is_ginst (klass) && !klass->methods) + return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class)); return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME); } @@ -9829,8 +9880,8 @@ mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int p mono_class_init (klass); - if (klass->generic_class && !klass->methods) { - res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags); + if (mono_class_is_ginst (klass) && !klass->methods) { + res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags); if (res) { MonoError error; res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error); @@ -9960,6 +10011,7 @@ mono_classes_init (void) mono_os_mutex_init (&classes_mutex); mono_native_tls_alloc (&setup_fields_tls_id, NULL); + mono_native_tls_alloc (&init_pending_tls_id, NULL); mono_counters_register ("Inflated methods size", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size); @@ -9982,6 +10034,7 @@ void mono_classes_cleanup (void) { mono_native_tls_free (setup_fields_tls_id); + mono_native_tls_free (init_pending_tls_id); if (global_interface_bitset) mono_bitset_free (global_interface_bitset); @@ -10024,7 +10077,8 @@ is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass) MonoClass * mono_class_get_generic_type_definition (MonoClass *klass) { - return klass->generic_class ? klass->generic_class->container_class : klass; + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); + return gklass ? gklass->container_class : klass; } /* @@ -10121,8 +10175,9 @@ static MonoClass* get_generic_definition_class (MonoClass *klass) { while (klass) { - if (klass->generic_class && klass->generic_class->container_class) - return klass->generic_class->container_class; + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); + if (gklass && gklass->container_class) + return gklass->container_class; klass = klass->parent; } return NULL; @@ -10181,7 +10236,7 @@ can_access_type (MonoClass *access_klass, MonoClass *member_klass) if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR) return TRUE; - if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst)) + if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst)) return FALSE; if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass))) @@ -10232,7 +10287,8 @@ can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal) return TRUE; - if (((access_klass->generic_class && access_klass->generic_class->container_class) || + MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass); + if (((access_gklass && access_gklass->container_class) || access_klass->generic_container) && (member_generic_def = get_generic_definition_class (member_klass))) { MonoClass *access_container; @@ -10240,7 +10296,7 @@ can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* if (access_klass->generic_container) access_container = access_klass; else - access_container = access_klass->generic_class->container_class; + access_container = access_gklass->container_class; if (can_access_member (access_container, member_generic_def, context_klass, access_level)) return TRUE; @@ -10586,8 +10642,8 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error) if (interface_count > 1) interfaces [1] = mono_class_bind_generic_parameters ( mono_defaults.generic_ireadonlylist_class, 1, args, FALSE); - } else if (klass->generic_class) { - MonoClass *gklass = klass->generic_class->container_class; + } else if (mono_class_is_ginst (klass)) { + MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; mono_class_setup_interfaces (gklass, error); if (!mono_error_ok (error)) { @@ -10598,7 +10654,7 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error) interface_count = gklass->interface_count; interfaces = mono_class_new0 (klass, MonoClass *, interface_count); for (i = 0; i < interface_count; i++) { - interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error); + interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error); if (!mono_error_ok (error)) { mono_class_set_type_load_failure (klass, "Could not setup the interfaces"); return; @@ -10628,7 +10684,7 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error) { MonoClass *klass = field->parent; MonoImage *image = klass->image; - MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL; + MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL; int field_idx = field - klass->fields; mono_error_init (error); @@ -10637,12 +10693,16 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error) MonoClassField *gfield = >d->fields [field_idx]; MonoType *gtype = mono_field_get_type_checked (gfield, error); if (!mono_error_ok (error)) { - mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error)); + char *full_name = mono_type_get_full_name (gtd); + mono_class_set_type_load_failure (klass, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name, gfield->name, field_idx, mono_error_get_message (error)); + g_free (full_name); } field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error); if (!mono_error_ok (error)) { - mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error)); + char *full_name = mono_type_get_full_name (klass); + mono_class_set_type_load_failure (klass, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error)); + g_free (full_name); } } else { const char *sig; @@ -10664,8 +10724,10 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error) mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE); if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) { - mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);; + char *full_name = mono_type_get_full_name (klass); + mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);; mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error)); + g_free (full_name); return; } @@ -10677,7 +10739,9 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error) field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error); if (!field->type) { - mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error)); + char *full_name = mono_type_get_full_name (klass); + mono_class_set_type_load_failure (klass, "Could not load type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error)); + g_free (full_name); } } } @@ -10687,7 +10751,7 @@ mono_field_resolve_flags (MonoClassField *field) { MonoClass *klass = field->parent; MonoImage *image = klass->image; - MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL; + MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL; int field_idx = field - klass->fields;