X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=9c72644a3775b529adcdf7edb369a70f71ce5788;hb=de3b35df91b2665577a649c8320cd97791045e46;hp=6218589a88e3c47b96ecacfff2701e05e5035e7a;hpb=3d023ebb029a2fc978126568a34f138f5a64e49c;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 6218589a88e..9c72644a377 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -77,6 +77,10 @@ static guint32 mono_field_resolve_flags (MonoClassField *field); static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup); static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass); +static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error); +static gpointer mono_class_get_exception_data (const MonoClass *klass); + + /* We use gclass recording to allow recursive system f types to be referenced by a parent. @@ -104,6 +108,11 @@ static int record_gclass_instantiation; static GSList *gclass_recorded_list; 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) { @@ -497,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; @@ -818,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; } /* @@ -829,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 @@ -1086,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); @@ -1132,6 +1127,15 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k result->sre_method = FALSE; result->signature = NULL; + if (method->wrapper_type) { + MonoMethodWrapper *mw = (MonoMethodWrapper*)method; + MonoMethodWrapper *resw = (MonoMethodWrapper*)result; + int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]); + + resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1)); + memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1)); + } + if (iresult->context.method_inst) { /* Set the generic_container of the result to the generic_container of method */ MonoGenericContainer *generic_container = mono_method_get_generic_container (method); @@ -1142,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; @@ -1296,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); @@ -1335,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)) @@ -1352,7 +1357,7 @@ fail: } /* - * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es + * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es */ static gboolean mono_type_has_exceptions (MonoType *type) @@ -1372,49 +1377,11 @@ mono_type_has_exceptions (MonoType *type) } void -mono_error_set_for_class_failure (MonoError *oerror, MonoClass *klass) +mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass) { - gpointer exception_data = mono_class_get_exception_data (klass); - - switch (mono_class_get_failure(klass)) { - case MONO_EXCEPTION_TYPE_LOAD: { - mono_error_set_type_load_class (oerror, klass, "Error Loading class"); - return; - } - case MONO_EXCEPTION_MISSING_METHOD: { - char *class_name = (char *)exception_data; - char *member_name = class_name + strlen (class_name) + 1; - - mono_error_set_method_load (oerror, klass, member_name, "Error Loading Method"); - return; - } - case MONO_EXCEPTION_MISSING_FIELD: { - char *class_name = (char *)exception_data; - char *member_name = class_name + strlen (class_name) + 1; - - mono_error_set_field_load (oerror, klass, member_name, "Error Loading Field"); - return; - } - case MONO_EXCEPTION_FILE_NOT_FOUND: { - char *msg_format = (char *)exception_data; - char *assembly_name = msg_format + strlen (msg_format) + 1; - char *msg = g_strdup_printf (msg_format, assembly_name); - - mono_error_set_assembly_load (oerror, assembly_name, msg); - return; - } - case MONO_EXCEPTION_BAD_IMAGE: { - mono_error_set_bad_image (oerror, NULL, (const char *)exception_data); - return; - } - case MONO_EXCEPTION_INVALID_PROGRAM: { - mono_error_set_invalid_program (oerror, (const char *)exception_data); - return; - } - default: { - g_assert_not_reached (); - } - } + g_assert (mono_class_has_failure (klass)); + MonoErrorBoxed *box = (MonoErrorBoxed*)mono_class_get_exception_data (klass); + mono_error_set_from_boxed (oerror, box); } @@ -1424,16 +1391,17 @@ mono_error_set_for_class_failure (MonoError *oerror, MonoClass *klass) * Allocate memory for some data belonging to CLASS, either from its image's mempool, * or from the heap. */ -static gpointer +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); } -static gpointer +gpointer mono_class_alloc0 (MonoClass *klass, int size) { gpointer res; @@ -1450,13 +1418,18 @@ mono_class_alloc0 (MonoClass *klass, int size) * mono_class_setup_basic_field_info: * @class: The class to initialize * - * Initializes the klass->fields. - * LOCKING: Assumes the loader lock is held. + * Initializes the following fields in MonoClass: + * * klass->fields (only field->parent and field->name) + * * klass->field.count + * * klass->field.first + * LOCKING: Acquires the loader lock */ static void mono_class_setup_basic_field_info (MonoClass *klass) { + MonoGenericClass *gklass; MonoClassField *field; + MonoClassField *fields; MonoClass *gtd; MonoImage *image; int i, top; @@ -1464,11 +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; - top = klass->field.count; - 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 @@ -1481,18 +1455,21 @@ mono_class_setup_basic_field_info (MonoClass *klass) if (gtd) { mono_class_setup_basic_field_info (gtd); - top = gtd->field.count; + mono_loader_lock (); klass->field.first = gtd->field.first; klass->field.count = gtd->field.count; + mono_loader_unlock (); } - klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top); + top = klass->field.count; + + fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top); /* * Fetch all the field information. */ for (i = 0; i < top; i++){ - field = &klass->fields [i]; + field = &fields [i]; field->parent = klass; if (gtd) { @@ -1505,81 +1482,77 @@ mono_class_setup_basic_field_info (MonoClass *klass) field->name = mono_metadata_string_heap (image, name_idx); } } + + mono_memory_barrier (); + + mono_loader_lock (); + if (!klass->fields) + klass->fields = fields; + mono_loader_unlock (); +} + +/** + * mono_class_set_failure_causedby_class: + * @klass: the class that is failing + * @caused_by: the class that caused the failure + * @msg: Why @klass is failing. + * + * If @caused_by has a failure, sets a TypeLoadException failure on + * @klass with message "@msg, due to: {@caused_by message}". + * + * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure. + */ +static gboolean +mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg) +{ + if (mono_class_has_failure (caused_by)) { + MonoError cause_error; + mono_error_init (&cause_error); + mono_error_set_for_class_failure (&cause_error, caused_by); + mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error)); + mono_error_cleanup (&cause_error); + return TRUE; + } else { + return FALSE; + } } + /** * mono_class_setup_fields: - * @class: The class to initialize + * @klass: The class to initialize * - * Initializes the klass->fields. - * LOCKING: Assumes the loader lock is held. + * Initializes klass->fields, computes class layout and sizes. + * typebuilder_setup_fields () is the corresponding function for dynamic classes. + * Sets the following fields in @klass: + * - 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. */ -static void +void mono_class_setup_fields (MonoClass *klass) { MonoError error; MonoImage *m = klass->image; int top; guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK; - int i, blittable = TRUE; + int i; guint32 real_size = 0; guint32 packing_size = 0; int instance_size; gboolean explicit_size; MonoClassField *field; MonoGenericContainer *container = NULL; - MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL; + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); + MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL; - /* - * FIXME: We have a race condition here. It's possible that this function returns - * to its caller with `instance_size` set to `0` instead of the actual size. This - * is not a problem when the function is called recursively on the same class, - * because the size will be initialized by the outer invocation. What follows is a - * description of how it can occur in other cases, too. There it is a problem, - * because it can lead to the GC being asked to allocate an object of size `0`, - * which SGen chokes on. The race condition is triggered infrequently by - * `tests/sgen-suspend.cs`. - * - * This function is called for a class whenever one of its subclasses is inited. - * For example, it's called for every subclass of Object. What it does is this: - * - * if (klass->setup_fields_called) - * return; - * ... - * klass->instance_size = 0; - * ... - * klass->setup_fields_called = 1; - * ... critical point - * klass->instance_size = actual_instance_size; - * - * The last two steps are sometimes reversed, but that only changes the way in which - * the race condition works. - * - * Assume thread A goes through this function and makes it to the critical point. - * Now thread B runs the function and, since `setup_fields_called` is set, returns - * immediately, but `instance_size` is incorrect. - * - * The other case looks like this: - * - * if (klass->setup_fields_called) - * return; - * ... critical point X - * klass->instance_size = 0; - * ... critical point Y - * klass->instance_size = actual_instance_size; - * ... - * klass->setup_fields_called = 1; - * - * Assume thread A goes through the function and makes it to critical point X. Now - * thread B runs through the whole of the function, returning, assuming - * `instance_size` is set. At that point thread A gets to run and makes it to - * critical point Y, at which time `instance_size` is `0` again, invalidating thread - * B's assumption. - */ - if (klass->setup_fields_called) + 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 @@ -1592,101 +1565,53 @@ mono_class_setup_fields (MonoClass *klass) mono_class_setup_basic_field_info (klass); top = klass->field.count; + gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL; if (gtd) { mono_class_setup_fields (gtd); - if (mono_class_has_failure (gtd)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed")) return; - } } instance_size = 0; - if (!klass->rank) - klass->sizes.class_size = 0; - if (klass->parent) { /* For generic instances, klass->parent might not have been initialized */ mono_class_init (klass->parent); - if (!klass->parent->size_inited) { - mono_class_setup_fields (klass->parent); - if (mono_class_has_failure (klass->parent)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); - return; - } - } - instance_size += klass->parent->instance_size; - klass->min_align = klass->parent->min_align; - /* we use |= since it may have been set already */ - klass->has_references |= klass->parent->has_references; - blittable = klass->parent->blittable; + mono_class_setup_fields (klass->parent); + if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class")) + return; + instance_size = klass->parent->instance_size; } else { instance_size = sizeof (MonoObject); - klass->min_align = 1; } - /* We can't really enable 16 bytes alignment until the GC supports it. - The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the - boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type. - Bug #506144 is an example of this issue. - - if (klass->simd_type) - klass->min_align = 16; - */ /* Get the real size */ explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size); + if (explicit_size) + instance_size += real_size; - if (explicit_size) { - if ((packing_size & 0xffffff00) != 0) { - char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg); - return; - } - klass->packing_size = packing_size; - real_size += instance_size; - } - - if (!top) { - if (explicit_size && real_size) { - instance_size = MAX (real_size, instance_size); - } - klass->blittable = blittable; - if (!klass->instance_size) - klass->instance_size = instance_size; - mono_memory_barrier (); - klass->size_inited = 1; - klass->fields_inited = 1; - klass->setup_fields_called = 1; + /* + * This function can recursively call itself. + * Prevent infinite recursion by using a list in TLS. + */ + GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id); + if (g_slist_find (init_list, klass)) return; - } - - if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType"))) - blittable = FALSE; - - /* Prevent infinite loops if the class references itself */ - klass->setup_fields_called = 1; - - if (klass->generic_container) { - container = klass->generic_container; - } else if (gtd) { - container = gtd->generic_container; - g_assert (container); - } + init_list = g_slist_prepend (init_list, klass); + mono_native_tls_set_value (setup_fields_tls_id, init_list); /* * Fetch all the field information. */ - for (i = 0; i < top; i++){ + for (i = 0; i < top; i++) { int idx = klass->field.first + i; field = &klass->fields [i]; - field->parent = klass; - if (!field->type) { mono_field_resolve_type (field, &error); if (!mono_error_ok (&error)) { /*mono_field_resolve_type already failed class*/ mono_error_cleanup (&error); - return; + break; } if (!field->type) g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name); @@ -1695,58 +1620,29 @@ mono_class_setup_fields (MonoClass *klass) if (mono_field_is_deleted (field)) continue; - if (gtd) { - MonoClassField *gfield = >d->fields [i]; - field->offset = gfield->offset; - } else { - if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) { - guint32 offset; - mono_metadata_field_info (m, idx, &offset, NULL, NULL); - field->offset = offset; + if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) { + guint32 uoffset; + mono_metadata_field_info (m, idx, &uoffset, NULL, NULL); + int offset = uoffset; - if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name)); - break; - } - if (field->offset < -1) { /*-1 is used to encode special static fields */ - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name)); - break; - } - if (klass->generic_container) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout.")); - break; - } + if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { + mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name); + break; } - } - - /* Only do these checks if we still think this type is blittable */ - if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { - if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) { - blittable = FALSE; - } else { - MonoClass *field_class = mono_class_from_mono_type (field->type); - if (field_class) { - mono_class_setup_fields (field_class); - if (mono_class_has_failure (field_class)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); - break; - } - } - if (!field_class || !field_class->blittable) - blittable = FALSE; + if (offset < -1) { /*-1 is used to encode special static fields */ + mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset); + break; + } + if (klass->generic_container) { + mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout."); + break; } } - - if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { - klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type); - blittable = klass->element_class->blittable; - } - if (mono_type_has_exceptions (field->type)) { char *class_name = mono_type_get_full_name (klass); char *type_name = mono_type_full_name (field->type); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + mono_class_set_type_load_failure (klass, ""); g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name); g_free (class_name); g_free (type_name); @@ -1755,66 +1651,58 @@ mono_class_setup_fields (MonoClass *klass) /* The def_value of fields is compute lazily during vtable creation */ } - if (klass == mono_defaults.string_class) - blittable = FALSE; + if (!mono_class_has_failure (klass)) + mono_class_layout_fields (klass, instance_size, packing_size, FALSE); - klass->blittable = blittable; + init_list = g_slist_remove (init_list, klass); + mono_native_tls_set_value (setup_fields_tls_id, init_list); +} - if (klass->enumtype && !mono_class_enum_basetype (klass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); - return; +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; } - if (explicit_size && real_size) { - instance_size = MAX (real_size, instance_size); + else { + if (!klass->size_inited) + mono_class_setup_fields (klass); } - - if (mono_class_has_failure (klass)) - return; - mono_class_layout_fields (klass, instance_size); - - /*valuetypes can't be neither bigger than 1Mb or empty. */ - if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject)))) - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); - - mono_memory_barrier (); - klass->fields_inited = 1; } +/* -/** - * mono_class_setup_fields_locking: - * @class: The class to initialize + * mono_class_init_sizes: * - * Initializes the klass->fields array of fields. - * Aquires the loader lock. - */ -void -mono_class_setup_fields_locking (MonoClass *klass) -{ - /* This can be checked without locks */ - if (klass->fields_inited) - return; - mono_loader_lock (); - mono_class_setup_fields (klass); - mono_loader_unlock (); -} - -/* - * mono_class_has_references: + * 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); } /* @@ -1834,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; } @@ -1851,20 +1752,17 @@ type_has_references (MonoClass *klass, MonoType *ftype) /* * mono_class_layout_fields: * @class: a class - * @instance_size: base instance size + * @base_instance_size: base instance size + * @packing_size: * - * Compute the placement of fields inside an object or struct, according to - * the layout rules and set the following fields in @class: - * - 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) + * This contains the common code for computing the layout of classes and sizes. + * This should only be called from mono_class_setup_fields () and + * typebuilder_setup_fields (). * - * LOCKING: this is supposed to be called with the loader lock held. + * LOCKING: Acquires the loader lock */ void -mono_class_layout_fields (MonoClass *klass, int instance_size) +mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre) { int i; const int top = klass->field.count; @@ -1872,7 +1770,41 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) guint32 pass, passes, real_size; gboolean gc_aware_layout = FALSE; gboolean has_static_fields = FALSE; + gboolean has_references = FALSE; + gboolean has_static_refs = FALSE; MonoClassField *field; + gboolean blittable; + int instance_size = base_instance_size; + int class_size, min_align; + int *field_offsets; + + /* + * 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 (klass->fields_inited) + return; + + if ((packing_size & 0xffffff00) != 0) { + mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size); + return; + } + + if (klass->parent) { + min_align = klass->parent->min_align; + /* we use | since it may have been set already */ + has_references = klass->has_references | klass->parent->has_references; + } else { + min_align = 1; + } + /* We can't really enable 16 bytes alignment until the GC supports it. + The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the + boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type. + Bug #506144 is an example of this issue. + + if (klass->simd_type) + min_align = 16; + */ /* * When we do generic sharing we need to have layout @@ -1881,6 +1813,21 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) * container), so we don't return in that case anymore. */ + if (klass->enumtype) { + for (i = 0; i < top; i++) { + field = &klass->fields [i]; + if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { + klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type); + break; + } + } + + if (!mono_class_enum_basetype (klass)) { + mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid."); + return; + } + } + /* * Enable GC aware auto layout: in this mode, reference * fields are grouped together inside objects, increasing collector @@ -1896,59 +1843,72 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) gc_aware_layout = TRUE; } - /* Compute klass->has_references */ - /* - * Process non-static fields first, since static fields might recursively - * refer to the class itself. - */ - for (i = 0; i < top; i++) { - MonoType *ftype; - - field = &klass->fields [i]; - - if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { - ftype = mono_type_get_underlying_type (field->type); - ftype = mono_type_get_basic_type_from_generic (ftype); - if (type_has_references (klass, ftype)) - klass->has_references = TRUE; - } - } - + /* Compute klass->blittable */ + blittable = TRUE; + if (klass->parent) + blittable = klass->parent->blittable; + if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top) + blittable = FALSE; for (i = 0; i < top; i++) { - MonoType *ftype; - field = &klass->fields [i]; - if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) { - ftype = mono_type_get_underlying_type (field->type); - ftype = mono_type_get_basic_type_from_generic (ftype); - if (type_has_references (klass, ftype)) - klass->has_static_refs = TRUE; + if (mono_field_is_deleted (field)) + continue; + if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) + continue; + if (blittable) { + if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) { + blittable = FALSE; + } else { + MonoClass *field_class = mono_class_from_mono_type (field->type); + if (field_class) { + mono_class_setup_fields (field_class); + if (mono_class_has_failure (field_class)) { + MonoError field_error; + mono_error_init (&field_error); + mono_error_set_for_class_failure (&field_error, field_class); + mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error)); + mono_error_cleanup (&field_error); + break; + } + } + if (!field_class || !field_class->blittable) + blittable = FALSE; + } } + if (klass->enumtype) + blittable = klass->element_class->blittable; } + if (mono_class_has_failure (klass)) + return; + if (klass == mono_defaults.string_class) + blittable = FALSE; + /* Compute klass->has_references */ + /* + * Process non-static fields first, since static fields might recursively + * refer to the class itself. + */ for (i = 0; i < top; i++) { MonoType *ftype; field = &klass->fields [i]; - ftype = mono_type_get_underlying_type (field->type); - ftype = mono_type_get_basic_type_from_generic (ftype); - if (type_has_references (klass, ftype)) { - if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) - klass->has_static_refs = TRUE; - else - klass->has_references = TRUE; + if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { + ftype = mono_type_get_underlying_type (field->type); + ftype = mono_type_get_basic_type_from_generic (ftype); + if (type_has_references (klass, ftype)) + has_references = TRUE; } } /* * Compute field layout and total size (not considering static fields) */ + field_offsets = g_new0 (int, top); switch (layout) { case TYPE_ATTRIBUTE_AUTO_LAYOUT: case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT: - if (gc_aware_layout) passes = 2; else @@ -1959,10 +1919,8 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) if (klass->parent) { mono_class_setup_fields (klass->parent); - if (mono_class_has_failure (klass->parent)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class")) return; - } real_size = klass->parent->instance_size; } else { real_size = sizeof (MonoObject); @@ -1993,7 +1951,7 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) } } - if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) && + if ((top == 1) && (instance_size == sizeof (MonoObject)) && (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) { /* This field is a hack inserted by MCS to empty structures */ continue; @@ -2002,29 +1960,29 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) size = mono_type_size (field->type, &align); /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */ - align = klass->packing_size ? MIN (klass->packing_size, align): align; + align = packing_size ? MIN (packing_size, align): align; /* if the field has managed references, we need to force-align it * see bug #77788 */ if (type_has_references (klass, ftype)) align = MAX (align, sizeof (gpointer)); - klass->min_align = MAX (align, klass->min_align); - field->offset = real_size; + min_align = MAX (align, min_align); + field_offsets [i] = real_size; if (align) { - field->offset += align - 1; - field->offset &= ~(align - 1); + field_offsets [i] += align - 1; + field_offsets [i] &= ~(align - 1); } /*TypeBuilders produce all sort of weird things*/ - g_assert (image_is_dynamic (klass->image) || field->offset > 0); - real_size = field->offset + size; + g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0); + real_size = field_offsets [i] + size; } instance_size = MAX (real_size, instance_size); - if (instance_size & (klass->min_align - 1)) { - instance_size += klass->min_align - 1; - instance_size &= ~(klass->min_align - 1); + if (instance_size & (min_align - 1)) { + instance_size += min_align - 1; + instance_size &= ~(min_align - 1); } } break; @@ -2049,28 +2007,30 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) continue; size = mono_type_size (field->type, &align); - align = klass->packing_size ? MIN (klass->packing_size, align): align; - klass->min_align = MAX (align, klass->min_align); + align = packing_size ? MIN (packing_size, align): align; + min_align = MAX (align, min_align); - /* - * When we get here, field->offset is already set by the - * loader (for either runtime fields or fields loaded from metadata). - * The offset is from the start of the object: this works for both - * classes and valuetypes. - */ - field->offset += sizeof (MonoObject); + if (sre) { + /* Already set by typebuilder_setup_fields () */ + field_offsets [i] = field->offset + sizeof (MonoObject); + } else { + int idx = klass->field.first + i; + guint32 offset; + mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL); + field_offsets [i] = offset + sizeof (MonoObject); + } ftype = mono_type_get_underlying_type (field->type); ftype = mono_type_get_basic_type_from_generic (ftype); if (type_has_references (klass, ftype)) { - if (field->offset % sizeof (gpointer)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + if (field_offsets [i] % sizeof (gpointer)) { + mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name); } } /* * Calc max size. */ - real_size = MAX (real_size, size + field->offset); + real_size = MAX (real_size, size + field_offsets [i]); } if (klass->has_references) { @@ -2088,7 +2048,7 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) continue; ftype = mono_type_get_underlying_type (field->type); if (MONO_TYPE_IS_REFERENCE (ftype)) - ref_bitmap [field->offset / sizeof (gpointer)] = 1; + ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1; } for (i = 0; i < top; i++) { field = &klass->fields [i]; @@ -2100,9 +2060,8 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) // 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.", klass->name, field->offset); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg); + if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) { + mono_class_set_type_load_failure (klass, "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.", klass->name, field_offsets [i]); } #endif } @@ -2110,9 +2069,9 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) } instance_size = MAX (real_size, instance_size); - if (instance_size & (klass->min_align - 1)) { - instance_size += klass->min_align - 1; - instance_size &= ~(klass->min_align - 1); + if (instance_size & (min_align - 1)) { + instance_size += min_align - 1; + instance_size &= ~(min_align - 1); } break; } @@ -2127,25 +2086,46 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) * performance, and since the JIT memset/memcpy code assumes this and generates * unaligned accesses otherwise. See #78990 for a testcase. */ - if (mono_align_small_structs) { + if (mono_align_small_structs && top) { if (instance_size <= sizeof (MonoObject) + sizeof (gpointer)) - klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject)); + min_align = MAX (min_align, instance_size - sizeof (MonoObject)); } } + if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) + instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE); + else if (klass->byval_arg.type == MONO_TYPE_PTR) + instance_size = sizeof (MonoObject) + sizeof (gpointer); + + /* Publish the data */ + mono_loader_lock (); if (klass->instance_size && !klass->image->dynamic) { /* Might be already set using cached info */ g_assert (klass->instance_size == instance_size); } else { klass->instance_size = instance_size; } + klass->blittable = blittable; + klass->has_references = has_references; + klass->packing_size = packing_size; + klass->min_align = min_align; + for (i = 0; i < top; ++i) { + field = &klass->fields [i]; + if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) + klass->fields [i].offset = field_offsets [i]; + } + mono_memory_barrier (); klass->size_inited = 1; + mono_loader_unlock (); /* * Compute static field layout and size + * Static fields can reference the class itself, so this has to be + * done after instance_size etc. are initialized. */ - for (i = 0; i < top; i++){ + class_size = 0; + for (i = 0; i < top; i++) { gint32 align; guint32 size; @@ -2157,23 +2137,60 @@ mono_class_layout_fields (MonoClass *klass, int instance_size) continue; if (mono_type_has_exceptions (field->type)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name); break; } has_static_fields = TRUE; size = mono_type_size (field->type, &align); - field->offset = klass->sizes.class_size; + field_offsets [i] = class_size; /*align is always non-zero here*/ - field->offset += align - 1; - field->offset &= ~(align - 1); - klass->sizes.class_size = field->offset + size; + field_offsets [i] += align - 1; + field_offsets [i] &= ~(align - 1); + class_size = field_offsets [i] + size; } - if (has_static_fields && klass->sizes.class_size == 0) + if (has_static_fields && class_size == 0) /* Simplify code which depends on class_size != 0 if the class has static fields */ - klass->sizes.class_size = 8; + class_size = 8; + + /* Compute klass->has_static_refs */ + has_static_refs = FALSE; + for (i = 0; i < top; i++) { + MonoType *ftype; + + field = &klass->fields [i]; + + if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) { + ftype = mono_type_get_underlying_type (field->type); + ftype = mono_type_get_basic_type_from_generic (ftype); + if (type_has_references (klass, ftype)) + has_static_refs = TRUE; + } + } + + /*valuetypes can't be neither bigger than 1Mb or empty. */ + if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject)))) + mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size); + + /* Publish the data */ + mono_loader_lock (); + if (!klass->rank) + klass->sizes.class_size = class_size; + klass->has_static_refs = has_static_refs; + for (i = 0; i < top; ++i) { + field = &klass->fields [i]; + + if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) + field->offset = field_offsets [i]; + } + + mono_memory_barrier (); + klass->fields_inited = 1; + mono_loader_unlock (); + + g_free (field_offsets); } static MonoMethod* @@ -2207,7 +2224,7 @@ create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *si * Methods belonging to an interface are assigned a sequential slot starting * from 0. * - * On failure this function sets klass->exception_type + * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details */ void mono_class_setup_methods (MonoClass *klass) @@ -2218,18 +2235,15 @@ 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)) mono_class_setup_methods (gklass); - if (mono_class_has_failure (gklass)) { - /* FIXME make exception_data less opaque so it's possible to dup it here */ - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load")); + if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load")) return; - } /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */ count = gklass->method.count; @@ -2240,7 +2254,7 @@ mono_class_setup_methods (MonoClass *klass) gklass->methods [i], klass, mono_class_get_context (klass), &error); if (!mono_error_ok (&error)) { char *method = mono_method_full_name (gklass->methods [i], TRUE); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not inflate method %s due to %s", method, mono_error_get_message (&error))); + mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error)); g_free (method); mono_error_cleanup (&error); @@ -2346,7 +2360,7 @@ mono_class_setup_methods (MonoClass *klass) int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1); methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error); if (!methods [i]) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load method %d due to %s", i, mono_error_get_message (&error))); + mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error)); mono_error_cleanup (&error); } } @@ -2386,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, @@ -2422,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); @@ -2467,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]; @@ -2518,15 +2533,13 @@ 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); - if (mono_class_has_failure (gklass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load")); + if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load")) return; - } properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1); @@ -2651,15 +2664,13 @@ 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); - if (mono_class_has_failure (gklass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load")); + if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load")) return; - } first = gklass->ext->event.first; count = gklass->ext->event.count; @@ -2697,7 +2708,6 @@ mono_class_setup_events (MonoClass *klass) if (count) { mono_class_setup_methods (klass); if (mono_class_has_failure (klass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load")); return; } } @@ -2845,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); @@ -2864,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; @@ -3078,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 @@ -3095,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; @@ -3115,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; @@ -3137,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); @@ -3514,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 exception_type + * 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) @@ -3550,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; @@ -3559,7 +3569,7 @@ setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite) ifaces = mono_class_get_implemented_interfaces (k, &error); if (!mono_error_ok (&error)) { char *name = mono_type_get_full_name (k); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error))); + mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error)); g_free (name); mono_error_cleanup (&error); cur_slot = -1; @@ -3588,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++) { @@ -3626,7 +3635,7 @@ setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite) count = count_virtual_methods (ic); if (count == -1) { char *name = mono_type_get_full_name (ic); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name)); + mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name); g_free (name); cur_slot = -1; goto end; @@ -3669,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; @@ -3688,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 () @@ -3733,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); @@ -3747,7 +3760,7 @@ end: //printf ("JUST DONE: "); //print_implemented_interfaces (klass); - + return cur_slot; } @@ -3765,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 @@ -3796,18 +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_has_failure (klass->generic_class->container_class)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("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) @@ -3817,7 +3825,7 @@ mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup) if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass)) continue; if (!mono_class_check_vtable_constraints (arg, in_setup)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i)); + mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i); return FALSE; } } @@ -3832,7 +3840,8 @@ mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup) * - vtable * - vtable_size * Plus all the fields initialized by setup_interface_offsets (). - * If there is an error during vtable construction, klass->exception_type is set. + * If there is an error during vtable construction, klass->has_failure + * is set and details are stored in a MonoErrorBoxed. * * LOCKING: Acquires the loader lock. */ @@ -3877,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); @@ -3885,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; @@ -3900,7 +3909,7 @@ mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup) if (!is_ok (&error)) { mono_loader_unlock (); g_list_remove (in_setup, klass); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf("Could not load list of method overrides due to %s", mono_error_get_message (&error))); + mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error)); mono_error_cleanup (&error); return; } @@ -3913,7 +3922,7 @@ mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup) if (ok) mono_class_setup_vtable_general (klass, overrides, onum, in_setup); else - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides")); + mono_class_set_type_load_failure (klass, "Could not load list of method overrides"); g_free (overrides); @@ -4029,7 +4038,7 @@ check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *c cmsig = mono_method_signature (cm); imsig = mono_method_signature (im); if (!cmsig || !imsig) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method")); + mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method"); return FALSE; } @@ -4047,7 +4056,7 @@ check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *c if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) { char *body_name = mono_method_full_name (cm, TRUE); char *decl_name = mono_method_full_name (im, TRUE); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name)); + mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name); g_free (body_name); g_free (decl_name); return FALSE; @@ -4071,7 +4080,7 @@ check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *c cmsig = mono_method_signature (cm); imsig = mono_method_signature (im); if (!cmsig || !imsig) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method")); + mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method"); return FALSE; } @@ -4128,7 +4137,7 @@ check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *c if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) { char *body_name = mono_method_full_name (cm, TRUE); char *decl_name = mono_method_full_name (im, TRUE); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name)); + mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name); g_free (body_name); g_free (decl_name); return FALSE; @@ -4295,28 +4304,28 @@ verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum) MonoMethod *body = overrides [i * 2 + 1]; if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one")); + mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one"); return FALSE; } if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) { if (body->flags & METHOD_ATTRIBUTE_STATIC) - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type")); + mono_class_set_type_load_failure (klass, "Method must not be static to override a base type"); else - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type")); + mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type"); return FALSE; } if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) { if (body->flags & METHOD_ATTRIBUTE_STATIC) - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type")); + mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type"); else - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type")); + mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type"); return FALSE; } if (!mono_class_is_assignable_from_slow (decl->klass, klass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that is not extended or implemented by this type")); + mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type"); return FALSE; } @@ -4326,7 +4335,7 @@ verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum) if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) { char *body_name = mono_method_full_name (body, TRUE); char *decl_name = mono_method_full_name (decl, TRUE); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name)); + mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name); g_free (body_name); g_free (decl_name); return FALSE; @@ -4369,7 +4378,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o ifaces = mono_class_get_implemented_interfaces (klass, &error); if (!mono_error_ok (&error)) { char *name = mono_type_get_full_name (klass); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error))); + mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error)); g_free (name); mono_error_cleanup (&error); return; @@ -4386,12 +4395,8 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o mono_class_init (klass->parent); mono_class_setup_vtable_full (klass->parent, in_setup); - if (mono_class_has_failure (klass->parent)) { - char *name = mono_type_get_full_name (klass->parent); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name)); - g_free (name); + if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load")) return; - } max_vtsize += klass->parent->vtable_size; cur_slot = klass->parent->vtable_size; @@ -4419,16 +4424,14 @@ 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); - if (mono_class_has_failure (gklass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition")) return; - } tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size); klass->vtable_size = gklass->vtable_size; @@ -4436,9 +4439,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o if (gklass->vtable [i]) { MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error); if (!mono_error_ok (&error)) { - char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error)); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg); - g_free (err_msg); + mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error)); mono_error_cleanup (&error); return; } @@ -4511,7 +4512,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o int dslot; dslot = mono_method_get_vtable_slot (decl); if (dslot == -1) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + mono_class_set_type_load_failure (klass, ""); return; } @@ -4688,7 +4689,8 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o m1sig = mono_method_signature (m1); if (!cmsig || !m1sig) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + /* FIXME proper error message */ + mono_class_set_type_load_failure (klass, ""); return; } @@ -4705,7 +4707,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) { char *body_name = mono_method_full_name (cm, TRUE); char *decl_name = mono_method_full_name (m1, TRUE); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name)); + mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name); g_free (body_name); g_free (decl_name); goto fail; @@ -4790,7 +4792,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) { char *type_name = mono_type_get_full_name (klass); char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none"); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name)); + mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name); g_free (type_name); g_free (method_name); return; @@ -4798,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); @@ -4874,7 +4876,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o fail: { char *name = mono_type_get_full_name (klass); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name)); + mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name); g_free (name); if (override_map) g_hash_table_destroy (override_map); @@ -4902,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) { @@ -5050,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++) { @@ -5080,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); @@ -5104,59 +5115,45 @@ 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) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected")); + /* + * 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_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name)); + 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) mono_class_init (element_class); - if (mono_class_has_failure (element_class)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class")) goto leave; - } } 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_has_failure (gklass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init")); + 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) @@ -5164,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); @@ -5209,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. @@ -5226,23 +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_has_failure (gklass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + 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 */ @@ -5266,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)) @@ -5276,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; } } @@ -5284,45 +5250,85 @@ mono_class_init (MonoClass *klass) } } - if (klass->parent) { - int first_iface_slot; - /* This will compute klass->parent->vtable_size for some classes */ - mono_class_init (klass->parent); - if (mono_class_has_failure (klass->parent)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); - 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_has_failure (klass->parent)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); - 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)) - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation")); + 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); } @@ -5346,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) { @@ -5395,11 +5401,7 @@ mono_class_has_finalizer (MonoClass *klass) gboolean mono_is_corlib_image (MonoImage *image) { - /* FIXME: allow the dynamic case for our compilers and with full trust */ - if (image_is_dynamic (image)) - return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib"); - else - return image == mono_defaults.corlib; + return image == mono_defaults.corlib; } /* @@ -5528,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 @@ -5548,7 +5549,7 @@ init_com_from_comimport (MonoClass *klass) /* but it can not be made available for application (i.e. user code) since all COM calls * are considered native calls. In this case we fail with a TypeLoadException (just like * Silverlight 2 does */ - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + mono_class_set_type_load_failure (klass, ""); return; } } @@ -5592,12 +5593,13 @@ mono_class_setup_parent (MonoClass *klass, MonoClass *parent) if (!parent) { /* set the parent to something useful and safe, but mark the type as broken */ parent = mono_defaults.object_class; - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + 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 @@ -5697,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. */ @@ -5710,8 +5712,8 @@ fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data) static void mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg)); - mono_error_set_type_load_class (error, klass, msg); + mono_class_set_type_load_failure (klass, "%s", msg); + mono_error_set_type_load_class (error, klass, "%s", msg); } /** @@ -5759,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; @@ -5772,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; @@ -5805,7 +5812,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError parent = mono_class_inflate_generic_class_checked (parent, context, error); if (parent == NULL) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error))); + mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error)); goto parent_failure; } @@ -5814,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; } @@ -5837,7 +5844,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error); if (!mono_error_ok (error)) { /*FIXME implement a mono_class_set_failure_from_mono_error */ - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error))); + mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error)); mono_loader_unlock (); mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED); return NULL; @@ -5858,7 +5865,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError if (!mono_metadata_interfaces_from_typedef_full ( image, type_token, &interfaces, &icount, FALSE, context, error)){ - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error))); + mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error)); mono_loader_unlock (); mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED); return NULL; @@ -5908,7 +5915,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError if (!enum_basetype) { /*set it to a default value as the whole runtime can't handle this to be null*/ klass->cast_class = klass->element_class = mono_defaults.int32_class; - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error))); + mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error)); mono_loader_unlock (); mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED); return NULL; @@ -5922,7 +5929,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError * work. */ if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error))); + mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error)); mono_loader_unlock (); mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED); return NULL; @@ -5950,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; } @@ -5960,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 @@ -5968,13 +5975,13 @@ 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)) { /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/ klass->parent = mono_defaults.object_class; - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error)); mono_error_cleanup (&error); } } @@ -6006,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; @@ -6028,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; @@ -6080,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 (); @@ -6141,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 ); @@ -6212,14 +6221,13 @@ make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo) klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE); mono_memory_barrier (); klass->size_inited = 1; - klass->setup_fields_called = 1; mono_class_setup_supertypes (klass); if (count - pos > 0) { mono_class_setup_vtable (klass->parent); if (mono_class_has_failure (klass->parent)) - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces")); + mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces"); else setup_interface_offsets (klass, klass->parent->vtable_size, TRUE); } @@ -6419,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); @@ -6434,8 +6443,7 @@ mono_ptr_class_get (MonoType *type) result->image = el_class->image; result->inited = TRUE; result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); - /* Can pointers get boxed? */ - result->instance_size = sizeof (gpointer); + result->instance_size = sizeof (MonoObject) + sizeof (gpointer); result->cast_class = result->element_class = el_class; result->blittable = TRUE; @@ -6487,14 +6495,14 @@ 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); result->image = mono_defaults.corlib; /* need to fix... */ result->inited = TRUE; result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */ - /* Can pointers get boxed? */ - result->instance_size = sizeof (gpointer); + result->instance_size = sizeof (MonoObject) + sizeof (gpointer); result->cast_class = result->element_class = result; result->blittable = TRUE; @@ -6655,7 +6663,6 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) GSList *list, *rootlist = NULL; int nsize; char *name; - gboolean corlib_type = FALSE; g_assert (rank <= 255); @@ -6697,20 +6704,16 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) } } - /* for the building corlib use System.Array from it */ - if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) { - parent = mono_class_load_from_name (image, "System", "Array"); - corlib_type = TRUE; - } else { - parent = mono_defaults.array_class; - if (!parent->inited) - mono_class_init (parent); - } + parent = mono_defaults.array_class; + 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); @@ -6726,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 */ @@ -6736,7 +6739,11 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) { /*Arrays of those two types are invalid.*/ - mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL); + MonoError prepared_error; + mono_error_init (&prepared_error); + mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid."); + mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image)); + mono_error_cleanup (&prepared_error); } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) { if (!eclass->ref_info_handle || eclass->wastypebuilder) { g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type"); @@ -6749,12 +6756,11 @@ 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); - if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/ - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + 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.*/ klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE; @@ -6805,9 +6811,6 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) } klass->this_arg = klass->byval_arg; klass->this_arg.byref = 1; - if (corlib_type) { - klass->inited = 1; - } klass->generic_container = eclass->generic_container; @@ -6860,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; } @@ -6871,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; } @@ -6892,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; @@ -6921,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_locking (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 @@ -6940,7 +6943,7 @@ mono_class_data_size (MonoClass *klass) static MonoClassField * mono_class_get_field_idx (MonoClass *klass, int idx) { - mono_class_setup_fields_locking (klass); + mono_class_setup_fields (klass); if (mono_class_has_failure (klass)) return NULL; @@ -7022,7 +7025,7 @@ mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoTyp { int i; - mono_class_setup_fields_locking (klass); + mono_class_setup_fields (klass); if (mono_class_has_failure (klass)) return NULL; @@ -7060,7 +7063,7 @@ mono_class_get_field_token (MonoClassField *field) MonoClass *klass = field->parent; int i; - mono_class_setup_fields_locking (klass); + mono_class_setup_fields (klass); while (klass) { if (!klass->fields) @@ -8111,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)) @@ -8167,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]); @@ -8429,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]); @@ -8607,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); } @@ -9140,7 +9143,7 @@ mono_class_get_fields (MonoClass* klass, gpointer *iter) if (!iter) return NULL; if (!*iter) { - mono_class_setup_fields_locking (klass); + mono_class_setup_fields (klass); if (mono_class_has_failure (klass)) return NULL; /* start from the first */ @@ -9877,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); @@ -9927,21 +9930,63 @@ mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int p * * LOCKING: Acquires the loader lock. */ -gboolean -mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data) +static gboolean +mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error) { + g_assert (boxed_error != NULL); + if (mono_class_has_failure (klass)) return FALSE; mono_loader_lock (); - klass->exception_type = ex_type; - if (ex_data) - mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data); + klass->has_failure = 1; + mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error); mono_loader_unlock (); return TRUE; } +gboolean +mono_class_has_failure (const MonoClass *klass) +{ + g_assert (klass != NULL); + return klass->has_failure != 0; +} + + +/** + * mono_class_set_type_load_failure: + * @klass: class in which the failure was detected + * @fmt: Printf-style error message string. + * + * Collect detected failure informaion in the class for later processing. + * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class () + * Note that only the first failure is kept. + * + * Returns FALSE if a failure was already set on the class, or TRUE otherwise. + * + * LOCKING: Acquires the loader lock. + */ +gboolean +mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...) +{ + MonoError prepare_error; + va_list args; + + if (mono_class_has_failure (klass)) + return FALSE; + + mono_error_init (&prepare_error); + + va_start (args, fmt); + mono_error_vset_type_load_class (&prepare_error, klass, fmt, args); + va_end (args); + + MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image); + mono_error_cleanup (&prepare_error); + return mono_class_set_failure (klass, box); +} + /* * mono_class_get_exception_data: * @@ -9949,10 +9994,10 @@ mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data) * * LOCKING: Acquires the loader lock. */ -gpointer -mono_class_get_exception_data (MonoClass *klass) +static gpointer +mono_class_get_exception_data (const MonoClass *klass) { - return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA); + return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA); } /** @@ -9965,6 +10010,9 @@ 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); mono_counters_register ("Inflated classes", @@ -9985,6 +10033,9 @@ mono_classes_init (void) 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); global_interface_bitset = NULL; @@ -10002,55 +10053,12 @@ mono_classes_cleanup (void) MonoException* mono_class_get_exception_for_failure (MonoClass *klass) { - gpointer exception_data = mono_class_get_exception_data (klass); - - switch (mono_class_get_failure(klass)) { - case MONO_EXCEPTION_TYPE_LOAD: { - MonoString *name; - MonoException *ex; - char *str = mono_type_get_full_name (klass); - char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL; - name = mono_string_new (mono_domain_get (), str); - g_free (str); - ex = mono_get_exception_type_load (name, astr); - g_free (astr); - return ex; - } - case MONO_EXCEPTION_MISSING_METHOD: { - char *class_name = (char *)exception_data; - char *assembly_name = class_name + strlen (class_name) + 1; - - return mono_get_exception_missing_method (class_name, assembly_name); - } - case MONO_EXCEPTION_MISSING_FIELD: { - char *class_name = (char *)exception_data; - char *member_name = class_name + strlen (class_name) + 1; - - return mono_get_exception_missing_field (class_name, member_name); - } - case MONO_EXCEPTION_FILE_NOT_FOUND: { - char *msg_format = (char *)exception_data; - char *assembly_name = msg_format + strlen (msg_format) + 1; - char *msg = g_strdup_printf (msg_format, assembly_name); - MonoException *ex; - - ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name)); - - g_free (msg); - - return ex; - } - case MONO_EXCEPTION_BAD_IMAGE: { - return mono_get_exception_bad_image_format ((const char *)exception_data); - } - case MONO_EXCEPTION_INVALID_PROGRAM: { - return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", ""); - } - default: { - /* TODO - handle other class related failures */ - return mono_get_exception_execution_engine ("Unknown class failure"); - } - } + if (!mono_class_has_failure (klass)) + return NULL; + MonoError unboxed_error; + mono_error_init (&unboxed_error); + mono_error_set_for_class_failure (&unboxed_error, klass); + return mono_error_convert_to_exception (&unboxed_error); } static gboolean @@ -10069,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; } /* @@ -10166,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; @@ -10226,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))) @@ -10277,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; @@ -10285,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; @@ -10631,21 +10642,21 @@ 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)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces")); + mono_class_set_type_load_failure (klass, "Could not setup the interfaces"); return; } 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_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces")); + mono_class_set_type_load_failure (klass, "Could not setup the interfaces"); return; } } @@ -10673,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); @@ -10682,14 +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)) { - char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error)); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg); + 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)) { - char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error)); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg); + 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; @@ -10711,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);; - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error))); + 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; } @@ -10724,8 +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) { - char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error)); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg); + 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); } } } @@ -10735,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; @@ -10752,21 +10768,6 @@ mono_field_resolve_flags (MonoClassField *field) } } -/** - * mono_class_setup_basic_field_info: - * @class: The class to initialize - * - * Initializes the klass->fields array of fields. - * Aquires the loader lock. - */ -static void -mono_class_setup_basic_field_info_locking (MonoClass *klass) -{ - mono_loader_lock (); - mono_class_setup_basic_field_info (klass); - mono_loader_unlock (); -} - /** * mono_class_get_fields_lazy: * @klass: the MonoClass to act on @@ -10788,7 +10789,7 @@ mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter) if (!iter) return NULL; if (!*iter) { - mono_class_setup_basic_field_info_locking (klass); + mono_class_setup_basic_field_info (klass); if (!klass->fields) return NULL; /* start from the first */