guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
guint32 classes_size, class_ext_size;
+/* Low level lock which protects data structures in this module */
+static mono_mutex_t classes_mutex;
+
/* Function supplied by the runtime to find classes by name using information from the AOT file */
static MonoGetClassFromName get_class_from_name = NULL;
static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
-
-void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
-
-
/*
We use gclass recording to allow recursive system f types to be referenced by a parent.
static GSList *gclass_recorded_list;
typedef gboolean (*gclass_record_func) (MonoClass*, void*);
+static inline void
+classes_lock (void)
+{
+ mono_locks_acquire (&classes_mutex, ClassesLock);
+}
+
+static inline void
+classes_unlock (void)
+{
+ mono_locks_release (&classes_mutex, ClassesLock);
+}
+
/*
* LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
*/
mono_class_from_typeref (MonoImage *image, guint32 type_token)
{
MonoError error;
+ MonoClass *class = mono_class_from_typeref_checked (image, type_token, &error);
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
+ return class;
+}
+
+MonoClass *
+mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
+{
guint32 cols [MONO_TYPEREF_SIZE];
MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
guint32 idx;
const char *name, *nspace;
- MonoClass *res;
+ MonoClass *res = NULL;
MonoImage *module;
- if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, &error)) {
- mono_trace_warning (MONO_TRACE_TYPE, "Failed to resolve typeref from %s due to '%s'", image->name, mono_error_get_message (&error));
+ mono_error_init (error);
+
+ if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
return NULL;
- }
mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
- idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
- switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
- case MONO_RESOLTION_SCOPE_MODULE:
+ idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
+ switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
+ case MONO_RESOLUTION_SCOPE_MODULE:
/*
LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
This is not the observed behavior of existing implementations.
The defacto behavior is that it's just a typedef in disguise.
*/
/* a typedef in disguise */
- return mono_class_from_name (image, nspace, name);
- case MONO_RESOLTION_SCOPE_MODULEREF:
+ res = mono_class_from_name (image, nspace, name); /*FIXME proper error handling*/
+ goto done;
+
+ case MONO_RESOLUTION_SCOPE_MODULEREF:
module = mono_image_load_module (image, idx);
if (module)
- return mono_class_from_name (module, nspace, name);
- else {
- char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
- char *human_name;
-
- human_name = mono_stringify_assembly_name (&image->assembly->aname);
- mono_loader_set_error_type_load (msg, human_name);
- g_free (msg);
- g_free (human_name);
-
- return NULL;
- }
- case MONO_RESOLTION_SCOPE_TYPEREF: {
+ res = mono_class_from_name (module, nspace, name); /*FIXME proper error handling*/
+ goto done;
+
+ case MONO_RESOLUTION_SCOPE_TYPEREF: {
MonoClass *enclosing;
GList *tmp;
if (idx == mono_metadata_token_index (type_token)) {
- mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with self-referencing typeref token %08x.", image->name, type_token));
+ mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
return NULL;
}
- enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
- if (!enclosing)
+ enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
+ if (!mono_error_ok (error))
return NULL;
if (enclosing->nested_classes_inited && enclosing->ext) {
guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
- if (strcmp (nname, name) == 0) {
- MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error);
- if (!mono_error_ok (&error)) {
- mono_loader_set_error_from_mono_error (&error);
- mono_error_cleanup (&error); /*FIXME don't swallow error message.*/
- return NULL;
- }
- return res;
- }
+ if (strcmp (nname, name) == 0)
+ return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
}
}
g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
- return NULL;
+ goto done;
}
- case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
+ case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
break;
}
if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
- mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with invalid assemblyref token %08x.", image->name, idx));
+ mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
return NULL;
}
mono_assembly_get_assemblyref (image, idx - 1, &aname);
human_name = mono_stringify_assembly_name (&aname);
- mono_loader_set_error_assembly_load (human_name, image->assembly ? image->assembly->ref_only : FALSE);
- g_free (human_name);
-
+ mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
return NULL;
}
- return mono_class_from_name (image->references [idx - 1]->image, nspace, name);
+ res = mono_class_from_name (image->references [idx - 1]->image, nspace, name);
+
+done:
+ /* Generic case, should be avoided for when a better error is possible. */
+ if (!res && mono_error_ok (error)) {
+ char *name = mono_class_name_from_token (image, type_token);
+ char *assembly = mono_assembly_name_from_token (image, type_token);
+ mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
+ }
+ return res;
}
return inflated;
}
-static MonoClass*
+MonoClass*
mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
{
MonoClass *res;
iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
}
- mono_loader_lock ();
cached = mono_method_inflated_lookup (iresult, FALSE);
if (cached) {
- mono_loader_unlock ();
g_free (iresult);
return (MonoMethod*)cached;
}
* is_generic_method_definition().
*/
- mono_method_inflated_lookup (iresult, TRUE);
- mono_loader_unlock ();
- return result;
+ return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
fail:
- mono_loader_unlock ();
g_free (iresult);
return NULL;
}
* mono_method_set_generic_container:
*
* Sets the generic container of METHOD to CONTAINER.
- * LOCKING: Acquires the loader lock.
+ * LOCKING: Acquires the image lock.
*/
void
mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
* in a separate function since it is cheaper than calling mono_class_setup_fields.
*/
static MonoType*
-mono_class_find_enum_basetype (MonoClass *class)
+mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
{
MonoGenericContainer *container = NULL;
MonoImage *m = class->image;
g_assert (class->enumtype);
+ mono_error_init (error);
+
if (class->generic_container)
container = class->generic_container;
else if (class->generic_class) {
if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
continue;
- if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL))
- return NULL;
+ if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
+ mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
+ goto fail;
+ }
sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
mono_metadata_decode_value (sig, &sig);
/* FIELD signature == 0x06 */
- if (*sig != 0x06)
- return NULL;
+ if (*sig != 0x06) {
+ mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
+ goto fail;
+ }
ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
- if (!ftype)
- return NULL;
+ if (!ftype) {
+ if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
+ mono_error_set_from_loader_error (error);
+ else
+ mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
+ goto fail;
+ }
if (class->generic_class) {
//FIXME do we leak here?
- ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
+ ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
+ if (!mono_error_ok (error))
+ goto fail;
ftype->attrs = cols [MONO_FIELD_FLAGS];
}
return ftype;
}
+ mono_error_set_type_load_class (error, class, "Could not find base type");
+fail:
+ g_assert (!mono_loader_get_last_error ());
return NULL;
}
explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
if (explicit_size) {
- if ((packing_size & 0xfffffff0) != 0) {
- char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
+ if ((packing_size & 0xffffff00) != 0) {
+ char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
return;
}
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
break;
}
+ if (class->generic_container) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
+ break;
+ }
}
}
}
}
break;
- case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
+ case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
+ guint8 *ref_bitmap;
+
real_size = 0;
for (i = 0; i < top; i++) {
gint32 align;
* There must be info about all the fields in a type if it
* uses explicit layout.
*/
-
if (mono_field_is_deleted (field))
continue;
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
*/
real_size = MAX (real_size, size + field->offset);
}
+
+ if (class->has_references) {
+ ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
+
+ /* Check for overlapping reference and non-reference fields */
+ for (i = 0; i < top; i++) {
+ MonoType *ftype;
+
+ field = &class->fields [i];
+
+ if (mono_field_is_deleted (field))
+ continue;
+ if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+ continue;
+ ftype = mono_type_get_underlying_type (field->type);
+ if (MONO_TYPE_IS_REFERENCE (ftype))
+ ref_bitmap [field->offset / sizeof (gpointer)] = 1;
+ }
+ for (i = 0; i < top; i++) {
+ field = &class->fields [i];
+
+ if (mono_field_is_deleted (field))
+ continue;
+ if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+ continue;
+
+ // FIXME: Too much code does this
+#if 0
+ if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
+ char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset);
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
+ }
+#endif
+ }
+ g_free (ref_bitmap);
+ }
+
class->instance_size = MAX (real_size, class->instance_size);
if (class->instance_size & (class->min_align - 1)) {
class->instance_size += class->min_align - 1;
}
break;
}
+ }
if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
/*
* mono_class_setup_methods:
* @class: a class
*
- * Initializes the 'methods' array in the klass.
+ * Initializes the 'methods' array in CLASS.
* Calling this method should be avoided if possible since it allocates a lot
* of long-living MonoMethod structures.
* Methods belonging to an interface are assigned a sequential slot starting
void
mono_class_setup_methods (MonoClass *class)
{
- int i;
+ int i, count;
MonoMethod **methods;
if (class->methods)
return;
- mono_loader_lock ();
-
- if (class->methods) {
- mono_loader_unlock ();
- return;
- }
-
if (class->generic_class) {
MonoError error;
MonoClass *gklass = class->generic_class->container_class;
if (!gklass->exception_type)
mono_class_setup_methods (gklass);
if (gklass->exception_type) {
- /*FIXME make exception_data less opaque so it's possible to dup it here*/
+ /* FIXME make exception_data less opaque so it's possible to dup it here */
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
- mono_loader_unlock ();
return;
}
/* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
- class->method.count = gklass->method.count;
- methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (class->method.count + 1));
+ count = gklass->method.count;
+ methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
- for (i = 0; i < class->method.count; i++) {
+ for (i = 0; i < count; i++) {
methods [i] = mono_class_inflate_generic_method_full_checked (
gklass->methods [i], class, mono_class_get_context (class), &error);
if (!mono_error_ok (&error)) {
g_free (method);
mono_error_cleanup (&error);
- mono_loader_unlock ();
return;
}
}
MonoMethodSignature *sig;
int count_generic = 0, first_generic = 0;
int method_num = 0;
+ gboolean jagged_ctor = FALSE;
- class->method.count = 3 + (class->rank > 1? 2: 1);
+ count = 3 + (class->rank > 1? 2: 1);
mono_class_setup_interfaces (class, &error);
g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
+ if (class->rank == 1 && class->element_class->rank) {
+ jagged_ctor = TRUE;
+ class->method.count ++;
+ }
+
if (class->interface_count) {
count_generic = generic_array_methods (class);
- first_generic = class->method.count;
- class->method.count += class->interface_count * count_generic;
+ first_generic = count;
+ count += class->interface_count * count_generic;
}
- methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * class->method.count);
+ methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
sig = mono_metadata_signature_alloc (class->image, class->rank);
sig->ret = &mono_defaults.void_class->byval_arg;
amethod = create_array_method (class, ".ctor", sig);
methods [method_num++] = amethod;
}
+
+ if (jagged_ctor) {
+ /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
+ sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
+ sig->ret = &mono_defaults.void_class->byval_arg;
+ sig->pinvoke = TRUE;
+ sig->hasthis = TRUE;
+ for (i = 0; i < class->rank + 1; ++i)
+ sig->params [i] = &mono_defaults.int32_class->byval_arg;
+ amethod = create_array_method (class, ".ctor", sig);
+ methods [method_num++] = amethod;
+ }
+
/* element Get (idx11, [idx2, ...]) */
sig = mono_metadata_signature_alloc (class->image, class->rank);
sig->ret = &class->element_class->byval_arg;
for (i = 0; i < class->interface_count; i++)
setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
} else {
- methods = mono_class_alloc (class, sizeof (MonoMethod*) * class->method.count);
- for (i = 0; i < class->method.count; ++i) {
+ count = class->method.count;
+ methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
+ for (i = 0; i < count; ++i) {
int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
}
if (MONO_CLASS_IS_INTERFACE (class)) {
int slot = 0;
/*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
- for (i = 0; i < class->method.count; ++i) {
+ for (i = 0; i < count; ++i) {
if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
methods [i]->slot = slot++;
}
}
- /* Needed because of the double-checking locking pattern */
- mono_memory_barrier ();
+ mono_image_lock (class->image);
- class->methods = methods;
+ if (!class->methods) {
+ class->method.count = count;
- mono_loader_unlock ();
+ /* Needed because of the double-checking locking pattern */
+ mono_memory_barrier ();
+
+ class->methods = methods;
+ }
+
+ mono_image_unlock (class->image);
}
/*
}
}
- mono_loader_lock ();
+ mono_class_alloc_ext (class);
- if (class->ext && class->ext->properties) {
+ mono_image_lock (class->image);
+
+ if (class->ext->properties) {
/* We leak 'properties' which was allocated from the image mempool */
- mono_loader_unlock ();
+ mono_image_unlock (class->image);
return;
}
- mono_class_alloc_ext (class);
-
class->ext->property.first = first;
class->ext->property.count = count;
/* Leave this assignment as the last op in the function */
class->ext->properties = properties;
- mono_loader_unlock ();
+ mono_image_unlock (class->image);
}
static MonoMethod**
if (class->generic_class) {
MonoClass *gklass = class->generic_class->container_class;
- MonoGenericContext *context;
+ MonoGenericContext *context = NULL;
mono_class_setup_events (gklass);
if (gklass->exception_type) {
}
}
- mono_loader_lock ();
+ mono_class_alloc_ext (class);
- if (class->ext && class->ext->events) {
- mono_loader_unlock ();
+ mono_image_lock (class->image);
+
+ if (class->ext->events) {
+ mono_image_unlock (class->image);
return;
}
- mono_class_alloc_ext (class);
-
class->ext->event.first = first;
class->ext->event.count = count;
/* Leave this assignment as the last op in the function */
class->ext->events = events;
- mono_loader_unlock ();
+ mono_image_unlock (class->image);
}
/*
* Global pool of interface IDs, represented as a bitset.
- * LOCKING: this is supposed to be accessed with the loader lock held.
+ * LOCKING: Protected by the classes lock.
*/
static MonoBitSet *global_interface_bitset = NULL;
void
mono_unload_interface_ids (MonoBitSet *bitset)
{
- mono_loader_lock ();
+ classes_lock ();
mono_bitset_sub (global_interface_bitset, bitset);
- mono_loader_unlock ();
+ classes_unlock ();
}
void
mono_unload_interface_id (MonoClass *class)
{
if (global_interface_bitset && class->interface_id) {
- mono_loader_lock ();
+ classes_lock ();
mono_bitset_clear (global_interface_bitset, class->interface_id);
- mono_loader_unlock ();
+ classes_unlock ();
}
}
*
* Assign a unique integer ID to the interface represented by @class.
* The ID will positive and as small as possible.
- * LOCKING: this is supposed to be called with the loader lock held.
+ * LOCKING: Acquires the classes lock.
* Returns: the new ID.
*/
static guint
g_assert (MONO_CLASS_IS_INTERFACE (class));
+ classes_lock ();
+
if (!global_interface_bitset) {
global_interface_bitset = mono_bitset_new (128, 0);
}
mono_bitset_set (class->image->interface_bitset, iid);
}
+ classes_unlock ();
+
#ifndef MONO_SMALL_CONFIG
if (mono_print_vtable) {
int generic_id;
} else {
class->vtable_size = szarray_vtable_size[slot];
}
- class->has_finalize_inited = TRUE;
} else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
MonoClass *gklass = class->generic_class->container_class;
/* Generic instance case */
class->ghcimpl = gklass->ghcimpl;
- class->has_finalize = mono_class_has_finalizer (gklass);
- class->has_finalize_inited = TRUE;
class->has_cctor = gklass->has_cctor;
mono_class_setup_vtable (gklass);
mono_loader_unlock ();
- if (mono_debugger_class_init_func)
- mono_debugger_class_init_func (class);
-
return class->exception_type == MONO_EXCEPTION_NONE;
}
gboolean
mono_class_has_finalizer (MonoClass *klass)
{
- if (!klass->has_finalize_inited) {
- MonoClass *class = klass;
+ MonoClass *class = klass;
+ gboolean has_finalize = FALSE;
- mono_loader_lock ();
+ if (klass->has_finalize_inited)
+ return klass->has_finalize;
- /* Interfaces and valuetypes are not supposed to have finalizers */
- if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
- MonoMethod *cmethod = NULL;
+ /* Interfaces and valuetypes are not supposed to have finalizers */
+ if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
+ MonoMethod *cmethod = NULL;
- if (class->parent && class->parent->has_finalize) {
- class->has_finalize = 1;
- } else {
- if (class->parent) {
- /*
- * Can't search in metadata for a method named Finalize, because that
- * ignores overrides.
- */
- mono_class_setup_vtable (class);
- if (class->exception_type || mono_loader_get_last_error ())
- goto leave;
+ if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
+ } else if (class->generic_class) {
+ MonoClass *gklass = class->generic_class->container_class;
+
+ has_finalize = mono_class_has_finalizer (gklass);
+ } else if (class->parent && class->parent->has_finalize) {
+ has_finalize = TRUE;
+ } else {
+ if (class->parent) {
+ /*
+ * Can't search in metadata for a method named Finalize, because that
+ * ignores overrides.
+ */
+ mono_class_setup_vtable (class);
+ if (class->exception_type || mono_loader_get_last_error ())
+ cmethod = NULL;
+ else
cmethod = class->vtable [finalize_slot];
- }
+ }
- if (cmethod) {
- g_assert (class->vtable_size > finalize_slot);
+ if (cmethod) {
+ g_assert (class->vtable_size > finalize_slot);
- class->has_finalize = 0;
- if (class->parent) {
- if (cmethod->is_inflated)
- cmethod = ((MonoMethodInflated*)cmethod)->declaring;
- if (cmethod != default_finalize) {
- class->has_finalize = 1;
- }
- }
+ if (class->parent) {
+ if (cmethod->is_inflated)
+ cmethod = ((MonoMethodInflated*)cmethod)->declaring;
+ if (cmethod != default_finalize)
+ has_finalize = TRUE;
}
}
}
+ }
+
+ mono_image_lock (klass->image);
+
+ if (!klass->has_finalize_inited) {
+ klass->has_finalize = has_finalize ? 1 : 0;
mono_memory_barrier ();
klass->has_finalize_inited = TRUE;
-
- mono_loader_unlock ();
}
- return klass->has_finalize;
+ mono_image_unlock (klass->image);
- leave:
- mono_loader_unlock ();
- return FALSE;
+ return klass->has_finalize;
}
gboolean
class->byval_arg.data.klass = class;
class->byval_arg.type = MONO_TYPE_CLASS;
}
- parent = mono_class_get_full (image, parent_token, context);
+ parent = mono_class_get_checked (image, parent_token, error);
+ if (parent && context) /* Always inflate */
+ parent = mono_class_inflate_generic_class_checked (parent, context, error);
if (parent == NULL) {
- mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
goto parent_failure;
}
}
if (class->enumtype) {
- MonoType *enum_basetype = mono_class_find_enum_basetype (class);
+ MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
if (!enum_basetype) {
/*set it to a default value as the whole runtime can't handle this to be null*/
class->cast_class = class->element_class = mono_defaults.int32_class;
- mono_class_set_failure_and_error (class, error, "Could not enum basetype");
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
g_assert (!mono_loader_get_last_error ());
* We must do this after the class has been constructed to make certain recursive scenarios
* work.
*/
- if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
- mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
+ if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
g_assert (!mono_loader_get_last_error ());
#define FAST_CACHE_SIZE 16
+/*
+ * LOCKING: Takes the image lock depending on @take_lock.
+ */
static MonoClass *
-get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
+get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
{
int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
MonoImage *image = param->image;
else
return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
} else {
+ MonoClass *klass = NULL;
ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
- return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
+ if (ht) {
+ if (take_lock)
+ mono_image_lock (image);
+ klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
+ if (take_lock)
+ mono_image_unlock (image);
+ }
+ return klass;
}
}
/*
- * LOCKING: Acquires the loader lock.
+ * LOCKING: Image lock (param->image) must be held
*/
static void
set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
{
int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
MonoImage *image = param->image;
- GHashTable *ht;
g_assert (image);
if (n < FAST_CACHE_SIZE) {
if (is_mvar) {
- /* No locking needed */
+ /* Requires locking to avoid droping an already published class */
if (!image->mvar_cache_fast)
image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
image->mvar_cache_fast [n] = klass;
image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
image->var_cache_fast [n] = klass;
}
- return;
- }
- ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
- if (!ht) {
- mono_loader_lock ();
- ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
+ } else {
+ GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
if (!ht) {
- ht = g_hash_table_new (NULL, NULL);
- mono_memory_barrier ();
- if (is_mvar)
- image->mvar_cache_slow = ht;
- else
- image->var_cache_slow = ht;
+ ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
+ if (!ht) {
+ ht = g_hash_table_new (NULL, NULL);
+ mono_memory_barrier ();
+ if (is_mvar)
+ image->mvar_cache_slow = ht;
+ else
+ image->var_cache_slow = ht;
+ }
}
- mono_loader_unlock ();
+ g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
}
-
- g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
}
/*
- * LOCKING: Acquires the loader lock.
+ * LOCKING: Acquires the image lock (@image).
*/
MonoClass *
mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
{
MonoGenericContainer *container = mono_generic_param_owner (param);
- MonoGenericParamInfo *pinfo;
- MonoClass *klass;
-
- mono_loader_lock ();
+ MonoGenericParamInfo *pinfo = NULL;
+ MonoClass *klass, *klass2;
if (container) {
pinfo = mono_generic_param_info (param);
- if (pinfo->pklass) {
- mono_loader_unlock ();
- return pinfo->pklass;
- }
+ klass = pinfo->pklass;
} else {
- pinfo = NULL;
image = NULL;
-
- klass = get_anon_gparam_class (param, is_mvar);
- if (klass) {
- mono_loader_unlock ();
- return klass;
- }
+ klass = get_anon_gparam_class (param, is_mvar, TRUE);
}
+ if (klass)
+ return klass;
if (!image && container) {
if (is_mvar) {
mono_memory_barrier ();
+ if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
+ image = mono_defaults.corlib;
+
+ mono_image_lock (image);
if (container)
- pinfo->pklass = klass;
+ klass2 = pinfo->pklass;
else
- set_anon_gparam_class (param, is_mvar, klass);
+ klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
- mono_loader_unlock ();
+ if (klass2) {
+ klass = klass2;
+ } else {
+ if (container)
+ pinfo->pklass = klass;
+ else
+ set_anon_gparam_class (param, is_mvar, klass);
+ }
+ mono_image_unlock (image);
/* FIXME: Should this go inside 'make_generic_param_klass'? */
- mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+ if (klass2)
+ mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
+ else
+ mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
return klass;
}
el_class = mono_class_from_mono_type (type);
image = el_class->image;
- mono_loader_lock ();
-
- if (!image->ptr_cache)
- image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
-
- if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
- mono_loader_unlock ();
- return result;
+ mono_image_lock (image);
+ if (image->ptr_cache) {
+ if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
+ mono_image_unlock (image);
+ return result;
+ }
}
+ mono_image_unlock (image);
+
result = mono_image_alloc0 (image, sizeof (MonoClass));
classes_size += sizeof (MonoClass);
mono_class_setup_supertypes (result);
+ mono_image_lock (image);
+ if (image->ptr_cache) {
+ MonoClass *result2;
+ if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
+ mono_image_unlock (image);
+ mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
+ return result2;
+ }
+ } else {
+ image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
+ }
g_hash_table_insert (image->ptr_cache, el_class, result);
-
- mono_loader_unlock ();
+ mono_image_unlock (image);
mono_profiler_class_loaded (result, MONO_PROFILE_OK);
static MonoType *
mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
{
- MonoType *t = mono_type_create_from_typespec (image, type_spec);
+ MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
- mono_error_init (error);
*did_inflate = FALSE;
- if (!t) {
- char *name = mono_class_name_from_token (image, type_spec);
- char *assembly = mono_assembly_name_from_token (image, type_spec);
- mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
+ if (!t)
return NULL;
- }
if (context && (context->class_inst || context->method_inst)) {
MonoType *inflated = inflate_generic_type (NULL, t, context, error);
- if (!mono_error_ok (error))
+ if (!mono_error_ok (error)) {
+ g_assert (!mono_loader_get_last_error ());
return NULL;
+ }
if (inflated) {
t = inflated;
g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
if (!klass->ext || !klass->ext->field_def_values) {
- mono_loader_lock ();
+ MonoFieldDefaultValue *def_values;
+
mono_class_alloc_ext (klass);
+
+ def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
+
+ mono_image_lock (klass->image);
+ mono_memory_barrier ();
if (!klass->ext->field_def_values)
- klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
- mono_loader_unlock ();
+ klass->ext->field_def_values = def_values;
+ mono_image_unlock (klass->image);
}
field_index = mono_field_get_index (field);
}
mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
- idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
- switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
- case MONO_RESOLTION_SCOPE_MODULE:
+ idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
+ switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
+ case MONO_RESOLUTION_SCOPE_MODULE:
/* FIXME: */
return g_strdup ("");
- case MONO_RESOLTION_SCOPE_MODULEREF:
+ case MONO_RESOLUTION_SCOPE_MODULEREF:
/* FIXME: */
return g_strdup ("");
- case MONO_RESOLTION_SCOPE_TYPEREF:
+ case MONO_RESOLUTION_SCOPE_TYPEREF:
/* FIXME: */
return g_strdup ("");
- case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
+ case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
mono_assembly_get_assemblyref (image, idx - 1, &aname);
return mono_stringify_assembly_name (&aname);
default:
* @image: the image where the class resides
* @type_token: the token for the class
* @context: the generic context used to evaluate generic instantiations in
+ * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
*
* Returns: the MonoClass that represents @type_token in @image
*/
mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
{
MonoError error;
+ MonoClass *class;
+ class = mono_class_get_checked (image, type_token, &error);
+
+ if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
+ class = mono_class_inflate_generic_class_checked (class, context, &error);
+
+ if (!class) {
+ mono_loader_set_error_from_mono_error (&error);
+ mono_error_cleanup (&error); /*FIXME don't swallow this error */
+ }
+ return class;
+}
+
+
+MonoClass *
+mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
+{
+ MonoClass *class;
+
+ mono_error_init (error);
+ class = mono_class_get_checked (image, type_token, error);
+
+ if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
+ class = mono_class_inflate_generic_class_checked (class, context, error);
+
+ return class;
+}
+/**
+ * mono_class_get_checked:
+ * @image: the image where the class resides
+ * @type_token: the token for the class
+ * @error: error object to return any error
+ *
+ * Returns: the MonoClass that represents @type_token in @image
+ */
+MonoClass *
+mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
+{
MonoClass *class = NULL;
+ mono_error_init (error);
+
if (image_is_dynamic (image)) {
int table = mono_metadata_token_table (type_token);
if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
- mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
+ mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
return NULL;
}
- return mono_lookup_dynamic_token (image, type_token, context);
+ class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
+ goto done;
}
switch (type_token & 0xff000000){
case MONO_TOKEN_TYPE_DEF:
- class = mono_class_create_from_typedef (image, type_token, &error);
- if (!mono_error_ok (&error)) {
- mono_loader_set_error_from_mono_error (&error);
- /*FIXME don't swallow the error message*/
- mono_error_cleanup (&error);
- return NULL;
- }
+ class = mono_class_create_from_typedef (image, type_token, error);
break;
case MONO_TOKEN_TYPE_REF:
- class = mono_class_from_typeref (image, type_token);
+ class = mono_class_from_typeref_checked (image, type_token, error);
break;
case MONO_TOKEN_TYPE_SPEC:
- class = mono_class_create_from_typespec (image, type_token, context, &error);
- if (!mono_error_ok (&error)) {
- /*FIXME don't swallow the error message*/
- mono_error_cleanup (&error);
- }
+ class = mono_class_create_from_typespec (image, type_token, NULL, error);
break;
default:
- g_warning ("unknown token type %x", type_token & 0xff000000);
- g_assert_not_reached ();
+ mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
}
- if (!class){
+done:
+ /* Generic case, should be avoided for when a better error is possible. */
+ if (!class && mono_error_ok (error)) {
char *name = mono_class_name_from_token (image, type_token);
char *assembly = mono_assembly_name_from_token (image, type_token);
- mono_loader_set_error_type_load (name, assembly);
- g_free (name);
- g_free (assembly);
+ mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
}
return class;
/**
- * mono_type_get_full:
+ * mono_type_get_checked:
* @image: the image where the type resides
* @type_token: the token for the type
* @context: the generic context used to evaluate generic instantiations in
+ * @error: Error handling context
*
* This functions exists to fullfill the fact that sometimes it's desirable to have access to the
*
* Returns: the MonoType that represents @type_token in @image
*/
MonoType *
-mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
+mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
{
- MonoError error;
MonoType *type = NULL;
gboolean inflated = FALSE;
+ mono_error_init (error);
+
//FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
if (image_is_dynamic (image))
return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
- MonoClass *class = mono_class_get_full (image, type_token, context);
- return class ? mono_class_get_type (class) : NULL;
- }
+ MonoClass *class = mono_class_get_checked (image, type_token, error);
- type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
+ if (!class) {
+ g_assert (!mono_loader_get_last_error ());
+ return NULL;
+ }
- if (!mono_error_ok (&error)) {
- /*FIXME don't swalloc the error message.*/
- char *name = mono_class_name_from_token (image, type_token);
- char *assembly = mono_assembly_name_from_token (image, type_token);
+ g_assert (class);
+ return mono_class_get_type (class);
+ }
- g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
+ type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
- mono_error_cleanup (&error);
- mono_loader_set_error_type_load (name, assembly);
+ if (!type) {
+ g_assert (!mono_loader_get_last_error ());
return NULL;
}
* @image: The MonoImage where the type is looked up in
* @name_space: the type namespace
* @name: the type short name.
+ * @deprecated: use the _checked variant
*
* Obtains a MonoClass with a given namespace and a given name which
* is located in the given MonoImage. The namespace and name
*/
MonoClass *
mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
+{
+ MonoError error;
+ MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
+ g_assert (!mono_error_ok (&error));
+ return res;
+}
+
+MonoClass *
+mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
{
MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
guint32 cols [MONO_TYPEDEF_SIZE];
const char *nspace;
guint32 i, visib;
+ mono_error_init (error);
+
if (image_is_dynamic (image)) {
guint32 token = 0;
FindUserData user_data;
mono_image_unlock (image);
if (token)
- return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
+ return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
else
return NULL;
n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
- return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
+ return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
}
return NULL;
}
case MONO_TOKEN_TYPE_DEF:
case MONO_TOKEN_TYPE_REF:
case MONO_TOKEN_TYPE_SPEC: {
+ MonoError error;
MonoType *type;
if (handle_class)
*handle_class = mono_defaults.typehandle_class;
- type = mono_type_get_full (image, token, context);
- if (!type)
+ type = mono_type_get_checked (image, token, context, &error);
+ if (!type) {
+ mono_loader_set_error_from_mono_error (&error);
+ mono_error_cleanup (&error); /* FIXME Don't swallow the error */
return NULL;
+ }
mono_class_init (mono_class_from_mono_type (type));
/* We return a MonoType* as handle */
return type;
}
case MONO_TOKEN_FIELD_DEF: {
MonoClass *class;
+ MonoError error;
guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
if (!type)
return NULL;
if (handle_class)
*handle_class = mono_defaults.fieldhandle_class;
- class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
- if (!class)
+ class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error);
+ if (!class) {
+ mono_loader_set_error_from_mono_error (&error);
+ mono_error_cleanup (&error); /* FIXME Don't swallow the error */
return NULL;
+ }
mono_class_init (class);
return mono_class_get_field (class, token);
}
sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
mono_metadata_decode_blob_size (sig, &sig);
if (*sig == 0x6) { /* it's a field */
+ MonoError error;
MonoClass *klass;
MonoClassField *field;
- field = mono_field_from_token (image, token, &klass, context);
+ field = mono_field_from_token_checked (image, token, &klass, context, &error);
if (handle_class)
*handle_class = mono_defaults.fieldhandle_class;
+ if (!field) {
+ mono_loader_set_error_from_mono_error (&error);
+ mono_error_cleanup (&error); /* FIXME Don't swallow the error */
+ }
return field;
} else {
MonoMethod *meth;
return NULL;
}
+static void
+setup_nested_types (MonoClass *klass)
+{
+ MonoError error;
+ GList *classes, *nested_classes, *l;
+ int i;
+
+ if (klass->nested_classes_inited)
+ return;
+
+ if (!klass->type_token)
+ klass->nested_classes_inited = TRUE;
+
+ i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
+ classes = NULL;
+ while (i) {
+ MonoClass* nclass;
+ guint32 cols [MONO_NESTED_CLASS_SIZE];
+ mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
+ nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
+ if (!mono_error_ok (&error)) {
+ /*FIXME don't swallow the error message*/
+ mono_error_cleanup (&error);
+
+ i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
+ continue;
+ }
+
+ classes = g_list_prepend (classes, nclass);
+
+ i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
+ }
+
+ mono_class_alloc_ext (klass);
+
+ nested_classes = NULL;
+ for (l = classes; l; l = l->next)
+ nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
+ g_list_free (classes);
+
+ mono_image_lock (klass->image);
+
+ mono_memory_barrier ();
+ if (!klass->nested_classes_inited) {
+ klass->ext->nested_classes = nested_classes;
+ mono_memory_barrier ();
+ klass->nested_classes_inited = TRUE;
+ }
+
+ mono_image_unlock (klass->image);
+}
+
/**
* mono_class_get_nested_types
* @klass: the MonoClass to act on
MonoClass*
mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
{
- MonoError error;
GList *item;
- int i;
if (!iter)
return NULL;
- if (!klass->nested_classes_inited) {
- if (!klass->type_token)
- klass->nested_classes_inited = TRUE;
- mono_loader_lock ();
- if (!klass->nested_classes_inited) {
- i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
- while (i) {
- MonoClass* nclass;
- guint32 cols [MONO_NESTED_CLASS_SIZE];
- mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
- nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
- if (!mono_error_ok (&error)) {
- /*FIXME don't swallow the error message*/
- mono_error_cleanup (&error);
-
- i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
- continue;
- }
- mono_class_alloc_ext (klass);
- klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass);
-
- i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
- }
- }
- mono_memory_barrier ();
- klass->nested_classes_inited = TRUE;
- mono_loader_unlock ();
- }
+ if (!klass->nested_classes_inited)
+ setup_nested_types (klass);
if (!*iter) {
/* start from the first */
guint32 rva;
int field_index;
MonoClass *klass = field->parent;
+ MonoFieldDefaultValue *field_def_values;
g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
if (!klass->ext || !klass->ext->field_def_values) {
- mono_loader_lock ();
mono_class_alloc_ext (klass);
+
+ field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
+
+ mono_image_lock (klass->image);
if (!klass->ext->field_def_values)
- klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
- mono_loader_unlock ();
+ klass->ext->field_def_values = field_def_values;
+ mono_image_unlock (klass->image);
}
field_index = mono_field_get_index (field);
void
mono_classes_init (void)
{
+ mono_mutex_init (&classes_mutex);
+
mono_counters_register ("Inflated methods size",
MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
mono_counters_register ("Inflated classes",
if (global_interface_bitset)
mono_bitset_free (global_interface_bitset);
global_interface_bitset = NULL;
+ mono_mutex_destroy (&classes_mutex);
}
/**
* mono_class_alloc_ext:
*
* Allocate klass->ext if not already done.
- * LOCKING: Assumes the loader lock is held.
*/
void
mono_class_alloc_ext (MonoClass *klass)
{
- if (!klass->ext) {
- klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
- class_ext_size += sizeof (MonoClassExt);
- }
+ MonoClassExt *ext;
+
+ if (klass->ext)
+ return;
+
+ ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
+ mono_image_lock (klass->image);
+ mono_memory_barrier ();
+ if (!klass->ext)
+ klass->ext = ext;
+ class_ext_size += sizeof (MonoClassExt);
+ mono_image_unlock (klass->image);
}
/*
void
mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
{
- int i;
+ int i, interface_count;
+ MonoClass **interfaces;
mono_error_init (error);
if (klass->interfaces_inited)
return;
- mono_loader_lock ();
-
- if (klass->interfaces_inited) {
- mono_loader_unlock ();
- return;
- }
-
if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
MonoType *args [1];
/* generic IList, ICollection, IEnumerable */
- klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
- klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
+ interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
+ interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
args [0] = &klass->element_class->byval_arg;
- klass->interfaces [0] = mono_class_bind_generic_parameters (
+ interfaces [0] = mono_class_bind_generic_parameters (
mono_defaults.generic_ilist_class, 1, args, FALSE);
- if (klass->interface_count > 1)
- klass->interfaces [1] = mono_class_bind_generic_parameters (
+ 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;
- klass->interface_count = gklass->interface_count;
- klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
- for (i = 0; i < klass->interface_count; i++) {
- klass->interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
+ 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"));
+ 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);
if (!mono_error_ok (error)) {
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
- klass->interfaces = NULL;
return;
}
}
+ } else {
+ interface_count = 0;
+ interfaces = NULL;
}
- mono_memory_barrier ();
+ mono_image_lock (klass->image);
- klass->interfaces_inited = TRUE;
+ if (!klass->interfaces_inited) {
+ klass->interface_count = interface_count;
+ klass->interfaces = interfaces;
- mono_loader_unlock ();
+ mono_memory_barrier ();
+
+ klass->interfaces_inited = TRUE;
+ }
+
+ mono_image_unlock (klass->image);
}
static void