static void free_inflated_method (MonoMethodInflated *method);
static void free_inflated_signature (MonoInflatedMethodSignature *sig);
static void mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image);
+static guint mono_metadata_generic_param_hash (MonoGenericParam *p);
/*
* This enumeration is used to describe the data types in the metadata
static GHashTable *type_cache = NULL;
static int next_generic_inst_id = 0;
+/* Protected by image_sets_mutex */
static MonoImageSet *mscorlib_image_set;
+/* Protected by image_sets_mutex */
static GPtrArray *image_sets;
+static CRITICAL_SECTION image_sets_mutex;
static guint mono_generic_class_hash (gconstpointer data);
for (i = 0; i < NBUILTIN_TYPES (); ++i)
g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
+
+ InitializeCriticalSection (&image_sets_mutex);
}
/**
type_cache = NULL;
g_ptr_array_free (image_sets, TRUE);
image_sets = NULL;
+ DeleteCriticalSection (&image_sets_mutex);
}
/**
}
}
+static inline void
+image_sets_lock (void)
+{
+ EnterCriticalSection (&image_sets_mutex);
+}
+
+static inline void
+image_sets_unlock (void)
+{
+ LeaveCriticalSection (&image_sets_mutex);
+}
+
/*
* get_image_set:
*
* Return a MonoImageSet representing the set of images in IMAGES.
- *
- * LOCKING: Assumes the loader lock is held.
*/
static MonoImageSet*
get_image_set (MonoImage **images, int nimages)
MonoImageSet *set;
GSList *l;
- if (!image_sets)
- image_sets = g_ptr_array_new ();
-
/* Common case */
if (nimages == 1 && images [0] == mono_defaults.corlib && mscorlib_image_set)
return mscorlib_image_set;
if (nimages == 0)
return mscorlib_image_set;
+ image_sets_lock ();
+
+ if (!image_sets)
+ image_sets = g_ptr_array_new ();
+
if (images [0] == mono_defaults.corlib && nimages > 1)
l = images [1]->image_sets;
else
g_ptr_array_add (image_sets, set);
}
- if (nimages == 1 && images [0] == mono_defaults.corlib)
+ if (nimages == 1 && images [0] == mono_defaults.corlib) {
+ mono_memory_barrier ();
mscorlib_image_set = set;
+ }
+
+ image_sets_unlock ();
return set;
}
g_hash_table_destroy (set->gmethod_cache);
g_hash_table_destroy (set->gsignature_cache);
+ image_sets_lock ();
+
for (i = 0; i < set->nimages; ++i)
set->images [i]->image_sets = g_slist_remove (set->images [i]->image_sets, set);
g_ptr_array_remove (image_sets, set);
+ image_sets_unlock ();
+
if (set->mempool)
mono_mempool_destroy (set->mempool);
g_free (set->images);
}
}
-GSList*
+void
mono_metadata_clean_for_image (MonoImage *image)
{
CleanForImageUserData ginst_data, gclass_data;
- GSList *l, *set_list, *free_list = NULL;
+ GSList *l, *set_list;
//check_image_sets (image);
for (l = image->image_sets; l; l = l->next) {
MonoImageSet *set = l->data;
+ mono_image_set_lock (set);
g_hash_table_foreach_steal (set->gclass_cache, steal_gclass_in_image, &gclass_data);
g_hash_table_foreach_steal (set->ginst_cache, steal_ginst_in_image, &ginst_data);
g_hash_table_foreach_remove (set->gmethod_cache, inflated_method_in_image, image);
g_hash_table_foreach_remove (set->gsignature_cache, inflated_signature_in_image, image);
+ mono_image_set_unlock (set);
}
/* Delete the removed items */
g_slist_free (set_list);
mono_loader_unlock ();
-
- return free_list;
}
static void
{
CollectData data;
MonoImageSet *set;
+ gpointer res;
collect_data_init (&data);
collect_data_free (&data);
if (cache) {
+ mono_image_set_lock (set);
g_hash_table_insert (set->gmethod_cache, method, method);
+ mono_image_set_unlock (set);
return method;
} else {
- return g_hash_table_lookup (set->gmethod_cache, method);
+ mono_image_set_lock (set);
+ res = g_hash_table_lookup (set->gmethod_cache, method);
+ mono_image_set_unlock (set);
+
+ return res;
}
}
CollectData data;
MonoImageSet *set;
- mono_loader_lock ();
-
helper.sig = sig;
helper.context.class_inst = context->class_inst;
helper.context.method_inst = context->method_inst;
collect_data_free (&data);
+ mono_image_set_lock (set);
+
res = g_hash_table_lookup (set->gsignature_cache, &helper);
if (!res) {
res = g_new0 (MonoInflatedMethodSignature, 1);
g_hash_table_insert (set->gsignature_cache, res, res);
}
- mono_loader_unlock ();
+ mono_image_set_unlock (set);
+
return res->sig;
}
ginst->type_argc = type_argc;
memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
- mono_loader_lock ();
-
collect_data_init (&data);
collect_ginst_images (ginst, &data);
collect_data_free (&data);
+ mono_image_set_lock (set);
+
ginst = g_hash_table_lookup (set->ginst_cache, ginst);
if (!ginst) {
ginst = mono_image_set_alloc0 (set, size);
g_hash_table_insert (set->ginst_cache, ginst, ginst);
}
- mono_loader_unlock ();
+ mono_image_set_unlock (set);
return ginst;
}
helper.is_tb_open = is_tb_open;
helper.cached_class = NULL;
- mono_loader_lock ();
-
collect_data_init (&data);
collect_gclass_images (&helper, &data);
collect_data_free (&data);
+ mono_image_set_lock (set);
+
gclass = g_hash_table_lookup (set->gclass_cache, &helper);
/* A tripwire just to keep us honest */
g_assert (!helper.cached_class);
if (gclass) {
- mono_loader_unlock ();
+ mono_image_set_unlock (set);
return gclass;
}
g_hash_table_insert (set->gclass_cache, gclass, gclass);
- mono_loader_unlock ();
+ mono_image_set_unlock (set);
return gclass;
}
return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
case MONO_TYPE_GENERICINST:
return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
+ return ((hash << 5) - hash) ^ mono_metadata_generic_param_hash (t1->data.generic_param);
}
return hash;
}
+static guint
+mono_metadata_generic_param_hash (MonoGenericParam *p)
+{
+ guint hash;
+ MonoGenericParamInfo *info;
+
+ hash = (mono_generic_param_num (p) << 2) | p->serial;
+ info = mono_generic_param_info (p);
+ /* Can't hash on the owner klass/method, since those might not be set when this is called */
+ if (info)
+ hash = ((hash << 5) - hash) ^ info->token;
+ return hash;
+}
+
static gboolean
mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, gboolean signature_only)
{
const char *p;
if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
- *marshal_spec = mono_metadata_parse_marshal_spec_full (alloc_from_image ? meta : NULL, p);
+ *marshal_spec = mono_metadata_parse_marshal_spec_full (alloc_from_image ? meta : NULL, meta, p);
}
}
MonoMarshalSpec *
mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
{
- return mono_metadata_parse_marshal_spec_full (NULL, ptr);
+ return mono_metadata_parse_marshal_spec_full (NULL, image, ptr);
}
+/*
+ * If IMAGE is non-null, memory will be allocated from its mempool, otherwise it will be allocated using malloc.
+ * PARENT_IMAGE is the image containing the marshal spec.
+ */
MonoMarshalSpec *
-mono_metadata_parse_marshal_spec_full (MonoImage *image, const char *ptr)
+mono_metadata_parse_marshal_spec_full (MonoImage *image, MonoImage *parent_image, const char *ptr)
{
MonoMarshalSpec *res;
int len;
/* read cookie string */
len = mono_metadata_decode_value (ptr, &ptr);
res->data.custom_data.cookie = mono_image_strndup (image, ptr, len);
+ res->data.custom_data.image = parent_image;
}
if (res->native == MONO_NATIVE_SAFEARRAY) {