X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=fa67e15b0f1404c942742c410d57ef2a714002a7;hb=86e44dfdcbc36134f56616dfe0ee1c6ae81e02b7;hp=ed14162510d11badbc487d7b615c825375583c8a;hpb=633af27d6800a6a5c050c9e4c50a0d8b67c97c20;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index ed14162510d..fa67e15b0f1 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,9 @@ 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 inline void classes_lock (void) { @@ -1361,7 +1368,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) @@ -1381,26 +1388,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_INVALID_PROGRAM: { - mono_error_set_invalid_program (oerror, "%s", (const char *)exception_data); - return; - } - case MONO_EXCEPTION_MISSING_METHOD: - case MONO_EXCEPTION_MISSING_FIELD: - case MONO_EXCEPTION_FILE_NOT_FOUND: - case MONO_EXCEPTION_BAD_IMAGE: - 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); } @@ -1436,13 +1428,17 @@ 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) { MonoClassField *field; + MonoClassField *fields; MonoClass *gtd; MonoImage *image; int i, top; @@ -1452,7 +1448,6 @@ mono_class_setup_basic_field_info (MonoClass *klass) gtd = klass->generic_class ? 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) { /* @@ -1467,18 +1462,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) { @@ -1491,78 +1489,78 @@ 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 klass->fields, computes class layout and sizes. + * typebuilder_setup_fields () is the corresponding function for dynamic classes. + * Sets the following fields in @klass: + * - packing_size + * - min_align + * - blittable + * - has_references (if the class contains instance references firled or structs that contain references) + * - has_static_refs (same, but for static fields) + * - instance_size (size of the object in memory) + * - class_size (size needed for the static fields) + * - size_inited (flag set when the instance_size is set) + * - element_class/cast_class (for enums) + * - fields_inited * - * Initializes the klass->fields. - * LOCKING: Assumes the loader lock is held. + * 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; + MonoClass *gtd; - /* - * 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) { @@ -1578,101 +1576,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); @@ -1681,58 +1631,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, mono_image_strdup_printf (klass->image, "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, mono_image_strdup_printf (klass->image, "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, mono_image_strdup_printf (klass->image, "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); @@ -1741,47 +1662,11 @@ 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; - - if (klass->enumtype && !mono_class_enum_basetype (klass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); - return; - } - if (explicit_size && real_size) { - instance_size = MAX (real_size, instance_size); - } - - 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 - * - * 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 (); + init_list = g_slist_remove (init_list, klass); + mono_native_tls_set_value (setup_fields_tls_id, init_list); } /* @@ -1837,20 +1722,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; @@ -1858,7 +1740,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 @@ -1867,6 +1783,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 @@ -1882,59 +1813,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. - */ + /* 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_references = 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]; - if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) { + 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; - } - } - - 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; + 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 @@ -1945,10 +1889,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); @@ -1979,7 +1921,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; @@ -1988,29 +1930,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; @@ -2035,28 +1977,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) { @@ -2074,7 +2018,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]; @@ -2086,9 +2030,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 = mono_image_strdup_printf (klass->image, "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 } @@ -2096,9 +2039,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; } @@ -2113,25 +2056,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; @@ -2143,23 +2107,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* @@ -2193,7 +2194,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) @@ -2211,11 +2212,8 @@ mono_class_setup_methods (MonoClass *klass) 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, mono_image_strdup (klass->image, "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; @@ -2226,7 +2224,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, mono_image_strdup_printf (klass->image, "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); @@ -2332,7 +2330,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, mono_image_strdup_printf (klass->image, "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); } } @@ -2509,10 +2507,8 @@ mono_class_setup_properties (MonoClass *klass) mono_class_init (gklass); mono_class_setup_properties (gklass); - if (mono_class_has_failure (gklass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "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); @@ -2642,10 +2638,8 @@ mono_class_setup_events (MonoClass *klass) MonoGenericContext *context = NULL; mono_class_setup_events (gklass); - if (mono_class_has_failure (gklass)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "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; @@ -2683,7 +2677,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, mono_image_strdup (klass->image, "Generic type definition failed to load")); return; } } @@ -3501,7 +3494,7 @@ mono_class_interface_match (const uint8_t *bitmap, int id) /* * 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. */ static int setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite) @@ -3545,7 +3538,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, mono_image_strdup_printf (klass->image, "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; @@ -3612,7 +3605,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, mono_image_strdup_printf (klass->image, "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; @@ -3788,10 +3781,8 @@ mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup) } 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, mono_image_strdup (klass->image, "Failed to load generic definition vtable")); + if (mono_class_set_type_load_failure_causedby_class (klass, klass->generic_class->container_class, "Failed to load generic definition vtable")) return FALSE; - } ginst = klass->generic_class->context.class_inst; for (i = 0; i < ginst->type_argc; ++i) { @@ -3803,7 +3794,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, mono_image_strdup_printf (klass->image, "Failed to load generic parameter %d", i)); + mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i); return FALSE; } } @@ -3818,7 +3809,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. */ @@ -3886,7 +3878,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, mono_image_strdup_printf(klass->image, "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; } @@ -3899,7 +3891,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, mono_image_strdup (klass->image, "Could not load list of method overrides")); + mono_class_set_type_load_failure (klass, "Could not load list of method overrides"); g_free (overrides); @@ -4015,7 +4007,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, mono_image_strdup (klass->image, "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; } @@ -4033,7 +4025,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, mono_image_strdup_printf (klass->image, "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; @@ -4057,7 +4049,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, mono_image_strdup (klass->image, "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; } @@ -4114,7 +4106,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, mono_image_strdup_printf (klass->image, "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; @@ -4281,28 +4273,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, mono_image_strdup (klass->image, "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, mono_image_strdup (klass->image, "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, mono_image_strdup (klass->image, "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, mono_image_strdup (klass->image, "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, mono_image_strdup (klass->image, "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, mono_image_strdup (klass->image, "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; } @@ -4312,7 +4304,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, mono_image_strdup_printf (klass->image, "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; @@ -4355,7 +4347,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, mono_image_strdup_printf (klass->image, "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; @@ -4372,12 +4364,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, mono_image_strdup_printf (klass->image, "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; @@ -4411,10 +4399,8 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o 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; @@ -4422,8 +4408,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 = mono_image_strdup_printf (klass->image, "Could not inflate method due to %s", mono_error_get_message (&error)); - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, 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; } @@ -4496,7 +4481,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; } @@ -4673,7 +4658,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; } @@ -4690,7 +4676,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, mono_image_strdup_printf (klass->image, "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; @@ -4775,7 +4761,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, mono_image_strdup_printf (klass->image, "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; @@ -4859,7 +4845,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, mono_image_strdup_printf (klass->image, "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); @@ -5099,14 +5085,14 @@ mono_class_init (MonoClass *klass) } if (klass->init_pending) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Recursive type definition detected")); + mono_class_set_type_load_failure (klass, "Recursive type definition detected"); goto leave; } klass->init_pending = 1; 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; } @@ -5115,10 +5101,8 @@ mono_class_init (MonoClass *klass) 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++; @@ -5135,10 +5119,8 @@ mono_class_init (MonoClass *klass) // 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, mono_image_strdup_printf (klass->image, "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); @@ -5222,10 +5204,8 @@ mono_class_init (MonoClass *klass) klass->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; } else { @@ -5270,18 +5250,18 @@ mono_class_init (MonoClass *klass) } if (klass->parent) { + MonoError parent_error; + mono_error_init (&parent_error); int first_iface_slot; /* This will compute klass->parent->vtable_size for some classes */ mono_class_init (klass->parent); - if (mono_class_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, "Parent class failed to initialize")) { goto leave; } if (!klass->parent->vtable_size) { /* FIXME: Get rid of this somehow */ mono_class_setup_vtable (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, "Parent class vtable failed to initialize")) { goto leave; } } @@ -5297,7 +5277,7 @@ mono_class_init (MonoClass *klass) 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, mono_image_strdup (klass->image, "Invalid generic instantiation")); + mono_class_set_type_load_failure (klass, "Invalid generic instantiation"); goto leave; @@ -5380,11 +5360,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; } /* @@ -5533,7 +5509,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; } } @@ -5577,7 +5553,8 @@ 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; @@ -5695,7 +5672,7 @@ 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, mono_image_strdup (klass->image, msg)); + mono_class_set_type_load_failure (klass, "%s", msg); mono_error_set_type_load_class (error, klass, "%s", msg); } @@ -5790,7 +5767,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, mono_image_strdup (klass->image, mono_error_get_message (error))); + mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error)); goto parent_failure; } @@ -5822,7 +5799,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, mono_image_strdup (klass->image, 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; @@ -5843,7 +5820,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, mono_image_strdup (klass->image, 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; @@ -5893,7 +5870,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, mono_image_strdup (klass->image, 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; @@ -5907,7 +5884,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, mono_image_strdup_printf (klass->image, "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; @@ -5959,7 +5936,7 @@ mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd) 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); } } @@ -6197,14 +6174,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, mono_image_strdup (klass->image, "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,8 +6395,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; @@ -6478,8 +6453,7 @@ mono_fnptr_class_get (MonoMethodSignature *sig) 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; @@ -6640,7 +6614,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); @@ -6682,15 +6655,9 @@ 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)); @@ -6721,7 +6688,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"); @@ -6738,8 +6709,8 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) 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_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; @@ -6790,9 +6761,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; @@ -6907,7 +6875,7 @@ mono_class_data_size (MonoClass *klass) mono_class_init (klass); /* This can happen with dynamically created types */ if (!klass->fields_inited) - mono_class_setup_fields_locking (klass); + mono_class_setup_fields (klass); /* in arrays, sizes.class_size is unioned with element_size * and arrays have no static fields @@ -6925,7 +6893,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; @@ -7007,7 +6975,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; @@ -7045,7 +7013,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) @@ -9125,7 +9093,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 */ @@ -9912,21 +9880,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: * @@ -9934,10 +9944,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); } /** @@ -9950,6 +9960,8 @@ mono_classes_init (void) { mono_os_mutex_init (&classes_mutex); + mono_native_tls_alloc (&setup_fields_tls_id, NULL); + mono_counters_register ("Inflated methods size", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size); mono_counters_register ("Inflated classes", @@ -9970,6 +9982,8 @@ mono_classes_init (void) void mono_classes_cleanup (void) { + mono_native_tls_free (setup_fields_tls_id); + if (global_interface_bitset) mono_bitset_free (global_interface_bitset); global_interface_bitset = NULL; @@ -9987,55 +10001,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 @@ -10621,7 +10592,7 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error) mono_class_setup_interfaces (gklass, error); if (!mono_error_ok (error)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Could not setup the interfaces")); + mono_class_set_type_load_failure (klass, "Could not setup the interfaces"); return; } @@ -10630,7 +10601,7 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error) 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); if (!mono_error_ok (error)) { - mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, mono_image_strdup (klass->image, "Could not setup the interfaces")); + mono_class_set_type_load_failure (klass, "Could not setup the interfaces"); return; } } @@ -10667,14 +10638,12 @@ 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 = mono_image_strdup_printf (klass->image, "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); + mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error)); } 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 = mono_image_strdup_printf (klass->image, "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); + mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error)); } } else { const char *sig; @@ -10697,7 +10666,7 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error) 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, mono_image_strdup (klass->image, mono_error_get_message (error))); + mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error)); return; } @@ -10709,8 +10678,7 @@ 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 = mono_image_strdup_printf (klass->image, "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); + mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error)); } } } @@ -10737,21 +10705,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 @@ -10773,7 +10726,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 */