#include <mono/utils/mono-logger-internals.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/atomic.h>
+#include <mono/utils/unlocked.h>
#include <mono/utils/bsearch.h>
#include <mono/utils/checked-build.h>
gboolean mono_align_small_structs = FALSE;
/* Statistics */
-guint32 inflated_classes_size, inflated_methods_size;
-guint32 classes_size, class_ext_size, class_ext_count;
-guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
+gint32 inflated_classes_size, inflated_methods_size;
+gint32 classes_size;
+gint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
/* Low level lock which protects data structures in this module */
static mono_mutex_t classes_mutex;
}
}
- mono_stats.inflated_type_count++;
+ UnlockedIncrement (&mono_stats.inflated_type_count);
return inflated;
}
if (!inflated)
return type;
- mono_stats.inflated_type_count++;
+ UnlockedIncrement (&mono_stats.inflated_type_count);
return inflated;
}
return (MonoMethod*)cached;
}
- mono_stats.inflated_method_count++;
+ UnlockedIncrement (&mono_stats.inflated_method_count);
- inflated_methods_size += sizeof (MonoMethodInflated);
+ UnlockedAdd (&inflated_methods_size, sizeof (MonoMethodInflated));
sig = mono_method_signature (method);
if (!sig) {
* Sets the following fields in \p klass:
* - all the fields initialized by mono_class_init_sizes ()
* - element_class/cast_class (for enums)
+ * - sizes:element_size (for arrays)
* - field->type/offset for all fields
* - fields_inited
*
MonoClassField *field;
gboolean blittable;
int instance_size = base_instance_size;
+ int element_size = -1;
int class_size, min_align;
int *field_offsets;
gboolean *fields_has_references;
else if (klass->byval_arg.type == MONO_TYPE_PTR)
instance_size = sizeof (MonoObject) + sizeof (gpointer);
+ if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY)
+ element_size = mono_class_array_element_size (klass->element_class);
+
/* Publish the data */
mono_loader_lock ();
if (klass->instance_size && !klass->image->dynamic) {
klass->fields [i].offset = field_offsets [i];
}
+ if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY)
+ klass->sizes.element_size = element_size;
+
mono_memory_barrier ();
klass->size_inited = 1;
mono_loader_unlock ();
*ifaces = g_hash_table_new (NULL, NULL);
if (g_hash_table_lookup (*ifaces, ic))
continue;
+ /* A gparam is not an implemented interface for the purposes of
+ * mono_class_get_implemented_interfaces */
+ if (mono_class_is_gparam (ic))
+ continue;
g_ptr_array_add (*res, ic);
g_hash_table_insert (*ifaces, ic, ic);
mono_class_init (ic);
for (i = 0; i < k->interface_count; i++) {
ic = k->interfaces [i];
- mono_class_init (ic);
+ /* A gparam does not have any interface_id set. */
+ if (! mono_class_is_gparam (ic))
+ mono_class_init (ic);
if (max_iid < ic->interface_id)
max_iid = ic->interface_id;
return;
}
- mono_stats.generic_vtable_count ++;
+ UnlockedIncrement (&mono_stats.generic_vtable_count);
in_setup = g_list_prepend (in_setup, klass);
if (mono_class_is_ginst (klass)) {
GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
if (g_slist_find (init_list, klass)) {
mono_class_set_type_load_failure (klass, "Recursive type definition detected");
- goto leave;
+ goto leave_no_init_pending;
}
init_list = g_slist_prepend (init_list, klass);
mono_native_tls_set_value (init_pending_tls_id, init_list);
goto leave;
}
- mono_stats.initialized_class_count++;
+ UnlockedIncrement (&mono_stats.initialized_class_count);
if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
return !mono_class_has_failure (klass);
}
- mono_stats.initialized_class_count++;
+ UnlockedIncrement (&mono_stats.initialized_class_count);
if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
- mono_stats.generic_class_count++;
+ UnlockedIncrement (&mono_stats.generic_class_count);
if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
klass->nested_classes_inited = TRUE;
goto leave;
- leave:
+leave:
+ init_list = mono_native_tls_get_value (init_pending_tls_id);
init_list = g_slist_remove (init_list, klass);
mono_native_tls_set_value (init_pending_tls_id, init_list);
+leave_no_init_pending:
if (locked)
mono_loader_unlock ();
* Create the MonoClass* representing the specified type token.
* \p type_token must be a TypeDef token.
*
- * FIXME: don't return NULL on failure, just the the caller figure it out.
+ * FIXME: don't return NULL on failure, just let the caller figure it out.
*/
static MonoClass *
mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
if (mono_metadata_has_generic_params (image, type_token)) {
klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
klass->class_kind = MONO_CLASS_GTD;
- classes_size += sizeof (MonoClassGtd);
+ UnlockedAdd (&classes_size, sizeof (MonoClassGtd));
++class_gtd_count;
} else {
klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
klass->class_kind = MONO_CLASS_DEF;
- classes_size += sizeof (MonoClassDef);
+ UnlockedAdd (&classes_size, sizeof (MonoClassDef));
++class_def_count;
}
klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
klass->class_kind = MONO_CLASS_GPARAM;
- classes_size += sizeof (MonoClassGenericParam);
- ++class_gparam_count;
+ UnlockedAdd (&classes_size, sizeof (MonoClassGenericParam));
+ UnlockedIncrement (&class_gparam_count);
if (pinfo) {
CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
- classes_size += sizeof (MonoClassPointer);
+ UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
++class_pointer_count;
result->parent = NULL; /* no parent for PTR types */
MONO_PROFILER_RAISE (class_loading, (result));
- classes_size += sizeof (MonoClassPointer);
+ UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
++class_pointer_count;
g_hash_table_insert (ptr_hash, sig, result);
/* element_size -1 is ok as this is not an instantitable type*/
klass->sizes.element_size = -1;
} else
- klass->sizes.element_size = mono_class_array_element_size (eclass);
+ klass->sizes.element_size = -1;
mono_class_setup_supertypes (klass);
MONO_PROFILER_RAISE (class_loading, (klass));
- classes_size += sizeof (MonoClassArray);
+ UnlockedAdd (&classes_size, sizeof (MonoClassArray));
++class_array_count;
if (rank == 1 && !bounded) {
* \param ac pointer to a \c MonoArrayClass
*
* \returns The size of single array element.
+ *
+ * LOCKING: Acquires the loader lock.
*/
gint32
mono_array_element_size (MonoClass *ac)
{
g_assert (ac->rank);
+ if (G_UNLIKELY (!ac->size_inited)) {
+ mono_class_setup_fields (ac);
+ }
return ac->sizes.element_size;
}
* mono_classes_init:
*
* Initialize the resources used by this module.
+ * Known racy counters: `class_gparam_count`, `classes_size` and `inflated_methods_size`
*/
+MONO_NO_SANITIZE_THREAD
void
mono_classes_init (void)
{