#include <mono/utils/mono-error-internals.h>
#include <mono/utils/bsearch.h>
#include <mono/utils/atomic.h>
+#include <mono/utils/mono-counters.h>
+
+static int img_set_cache_hit, img_set_cache_miss, img_set_count;
+
/* Auxiliary structure used for caching inflated signatures */
typedef struct {
#endif
+/* If TRUE (but also see DISABLE_STICT_STRONG_NAMES #define), Mono will check
+ * that the public key token, culture and version of a candidate assembly matches
+ * the requested strong name. If FALSE, as long as the name matches, the candidate
+ * will be allowed.
+ */
+static gboolean check_strong_names_strictly = FALSE;
+
// Amount initially reserved in each imageset's mempool.
// FIXME: This number is arbitrary, a more practical number should be found
#define INITIAL_IMAGE_SET_SIZE 1024
g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
mono_os_mutex_init_recursive (&image_sets_mutex);
+
+ mono_counters_register ("ImgSet Cache Hit", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_cache_hit);
+ mono_counters_register ("ImgSet Cache Miss", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_cache_miss);
+ mono_counters_register ("ImgSet Count", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_count);
}
/**
mono_os_mutex_unlock (&image_sets_mutex);
}
+static int
+compare_pointers (const void *a, const void *b)
+{
+ return (size_t)a - (size_t)b;
+}
+
+//1103, 1327, 1597
+#define HASH_TABLE_SIZE 1103
+static MonoImageSet *img_set_cache [HASH_TABLE_SIZE];
+
+static guint32
+mix_hash (uintptr_t source)
+{
+ unsigned int hash = source;
+
+ // Actual hash
+ hash = (((hash * 215497) >> 16) ^ ((hash * 1823231) + hash));
+
+ // Mix in highest bits on 64-bit systems only
+ if (sizeof (source) > 4)
+ hash = hash ^ (source >> 32);
+
+ return hash;
+}
+
+static guint32
+hash_images (MonoImage **images, int nimages)
+{
+ guint32 res = 0;
+ int i;
+ for (i = 0; i < nimages; ++i)
+ res += mix_hash ((size_t)images [i]);
+
+ return res;
+}
+
+static gboolean
+compare_img_set (MonoImageSet *set, MonoImage **images, int nimages)
+{
+ int j, k;
+
+ if (set->nimages != nimages)
+ return FALSE;
+
+ for (j = 0; j < nimages; ++j) {
+ for (k = 0; k < nimages; ++k)
+ if (set->images [k] == images [j])
+ break; // Break on match
+
+ // If we iterated all the way through set->images, images[j] was *not* found.
+ if (k == nimages)
+ break; // Break on "image not found"
+ }
+
+ // If we iterated all the way through images without breaking, all items in images were found in set->images
+ return j == nimages;
+}
+
+
+static MonoImageSet*
+img_set_cache_get (MonoImage **images, int nimages)
+{
+ guint32 hash_code = hash_images (images, nimages);
+ int index = hash_code % HASH_TABLE_SIZE;
+ MonoImageSet *img = img_set_cache [index];
+ if (!img || !compare_img_set (img, images, nimages)) {
+ ++img_set_cache_miss;
+ return NULL;
+ }
+ ++img_set_cache_hit;
+ return img;
+}
+
+static void
+img_set_cache_add (MonoImageSet *set)
+{
+ guint32 hash_code = hash_images (set->images, set->nimages);
+ int index = hash_code % HASH_TABLE_SIZE;
+ img_set_cache [index] = set;
+}
+
+static void
+img_set_cache_remove (MonoImageSet *is)
+{
+ guint32 hash_code = hash_images (is->images, is->nimages);
+ int index = hash_code % HASH_TABLE_SIZE;
+ if (img_set_cache [index] == is)
+ img_set_cache [index] = NULL;
+}
/*
* get_image_set:
*
if (nimages == 0)
return mscorlib_image_set;
+ set = img_set_cache_get (images, nimages);
+ if (set)
+ return set;
+
image_sets_lock ();
if (!image_sets)
mono_os_mutex_init_recursive (&set->lock);
for (i = 0; i < nimages; ++i)
set->images [i] = images [i];
- set->gclass_cache = g_hash_table_new_full (mono_generic_class_hash, mono_generic_class_equal, NULL, (GDestroyNotify)free_generic_class);
+ set->gclass_cache = mono_conc_hashtable_new_full (mono_generic_class_hash, mono_generic_class_equal, NULL, (GDestroyNotify)free_generic_class);
set->ginst_cache = g_hash_table_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst);
set->gmethod_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method);
set->gsignature_cache = g_hash_table_new_full (inflated_signature_hash, inflated_signature_equal, NULL, (GDestroyNotify)free_inflated_signature);
set->images [i]->image_sets = g_slist_prepend (set->images [i]->image_sets, set);
g_ptr_array_add (image_sets, set);
+ ++img_set_count;
+
+ img_set_cache_add (set);
}
if (nimages == 1 && images [0] == mono_defaults.corlib) {
{
int i;
- g_hash_table_destroy (set->gclass_cache);
+ mono_conc_hashtable_destroy (set->gclass_cache);
g_hash_table_destroy (set->ginst_cache);
g_hash_table_destroy (set->gmethod_cache);
g_hash_table_destroy (set->gsignature_cache);
image_sets_unlock ();
+ img_set_cache_remove (set);
+
if (set->mempool)
mono_mempool_destroy (set->mempool);
g_free (set->images);
MonoImageSet *set = (MonoImageSet *)l->data;
mono_image_set_lock (set);
- g_hash_table_foreach_steal (set->gclass_cache, steal_gclass_in_image, &gclass_data);
+ mono_conc_hashtable_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);
return set;
}
+static gboolean
+type_is_gtd (MonoType *type)
+{
+ switch (type->type) {
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_VALUETYPE:
+ return mono_class_is_gtd (type->data.klass);
+ default:
+ return FALSE;
+ }
+}
+
/*
* mono_metadata_get_generic_inst:
*
ginst->type_argc = type_argc;
memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
+ for (i = 0; i < type_argc; ++i) {
+ MonoType *t = ginst->type_argv [i];
+ if (type_is_gtd (t)) {
+ ginst->type_argv [i] = mono_class_gtd_get_canonical_inst (t->data.klass);
+ }
+ }
+
return mono_metadata_get_canonical_generic_inst (ginst);
}
collect_data_free (&data);
- mono_image_set_lock (set);
-
- gclass = (MonoGenericClass *)g_hash_table_lookup (set->gclass_cache, &helper);
+ gclass = (MonoGenericClass *)mono_conc_hashtable_lookup (set->gclass_cache, &helper);
/* A tripwire just to keep us honest */
g_assert (!helper.cached_class);
- if (gclass) {
- mono_image_set_unlock (set);
+ if (gclass)
return gclass;
- }
gclass = mono_image_set_new0 (set, MonoGenericClass, 1);
if (is_dynamic)
if (inst == mono_class_get_generic_container (container_class)->context.class_inst && !is_tb_open)
gclass->cached_class = container_class;
- g_hash_table_insert (set->gclass_cache, gclass, gclass);
+ mono_image_set_lock (set);
+
+ MonoGenericClass *gclass2 = mono_conc_hashtable_insert (set->gclass_cache, gclass, gclass);
+ if (!gclass2)
+ gclass2 = gclass;
+
+ // g_hash_table_insert (set->gclass_cache, gclass, gclass);
mono_image_set_unlock (set);
- return gclass;
+ return gclass2;
}
/*
}
}
-/*
+/**
* mono_method_header_get_code:
- * @header: a MonoMethodHeader pointer
- * @code_size: memory location for returning the code size
- * @max_stack: memory location for returning the max stack
+ * \param header a \c MonoMethodHeader pointer
+ * \param code_size memory location for returning the code size
+ * \param max_stack memory location for returning the max stack
*
* Method header accessor to retreive info about the IL code properties:
* a pointer to the IL code itself, the size of the code and the max number
* of stack slots used by the code.
*
- * Returns: pointer to the IL code represented by the method header.
+ * \returns pointer to the IL code represented by the method header.
*/
const unsigned char*
mono_method_header_get_code (MonoMethodHeader *header, guint32* code_size, guint32* max_stack)
return header->code;
}
-/*
+/**
* mono_method_header_get_locals:
- * @header: a MonoMethodHeader pointer
- * @num_locals: memory location for returning the number of local variables
- * @init_locals: memory location for returning the init_locals flag
+ * \param header a \c MonoMethodHeader pointer
+ * \param num_locals memory location for returning the number of local variables
+ * \param init_locals memory location for returning the init_locals flag
*
* Method header accessor to retreive info about the local variables:
* an array of local types, the number of locals and whether the locals
* are supposed to be initialized to 0 on method entry
*
- * Returns: pointer to an array of types of the local variables
+ * \returns pointer to an array of types of the local variables
*/
MonoType**
mono_method_header_get_locals (MonoMethodHeader *header, guint32* num_locals, gboolean *init_locals)
return header->num_clauses;
}
-/*
+/**
* mono_method_header_get_clauses:
- * @header: a MonoMethodHeader pointer
- * @method: MonoMethod the header belongs to
- * @iter: pointer to a iterator
- * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
+ * \param header a \c MonoMethodHeader pointer
+ * \param method \c MonoMethod the header belongs to
+ * \param iter pointer to a iterator
+ * \param clause pointer to a \c MonoExceptionClause structure which will be filled with the info
*
- * Get the info about the exception clauses in the method. Set *iter to NULL to
+ * Get the info about the exception clauses in the method. Set \c *iter to NULL to
* initiate the iteration, then call the method repeatedly until it returns FALSE.
* At each iteration, the structure pointed to by clause if filled with the
* exception clause information.
*
- * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
+ * \returns TRUE if clause was filled with info, FALSE if there are no more exception
* clauses.
*/
int
}
}
-/*
+/**
* mono_type_size:
- * @t: the type to return the size of
- *
- * Returns: the number of bytes required to hold an instance of this
+ * \param t the type to return the size of
+ * \returns The number of bytes required to hold an instance of this
* type in memory
*/
int
return 0;
}
-/*
+/**
* mono_type_stack_size:
- * @t: the type to return the size it uses on the stack
- *
- * Returns: the number of bytes required to hold an instance of this
+ * \param t the type to return the size it uses on the stack
+ * \returns The number of bytes required to hold an instance of this
* type on the runtime stack
*/
int
return r;
}
+/**
+ * mono_signature_hash:
+ */
guint
mono_signature_hash (MonoMethodSignature *sig)
{
}
/**
- * @image: context where the image is created
- * @type_spec: typespec token
- * @deprecated use mono_type_create_from_typespec_checked that has proper error handling
+ * mono_type_create_from_typespec:
+ * \param image context where the image is created
+ * \param type_spec typespec token
+ * \deprecated use \c mono_type_create_from_typespec_checked that has proper error handling
*
- * Creates a MonoType representing the TypeSpec indexed by the @type_spec
+ * Creates a \c MonoType representing the \c TypeSpec indexed by the \p type_spec
* token.
*/
MonoType *
error_init (error);
- mono_image_lock (image);
- type = (MonoType *)g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
- mono_image_unlock (image);
+ type = (MonoType *)mono_conc_hashtable_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
if (type)
return type;
mono_metadata_free_type (type);
mono_image_lock (image);
- type = (MonoType *)g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
+
/* We might leak some data in the image mempool if found */
- if (!type) {
- g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
+ type = mono_conc_hashtable_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
+ if (!type)
type = type2;
- }
+
mono_image_unlock (image);
return type;
/**
* mono_type_to_unmanaged:
- *
- * Returns: A MonoMarshalNative enumeration value (MONO_NATIVE_) value
+ * The value pointed to by \p conv will contain the kind of marshalling required for this
+ * particular type one of the \c MONO_MARSHAL_CONV_ enumeration values.
+ * \returns A \c MonoMarshalNative enumeration value (<code>MONO_NATIVE_</code>) value
* describing the underlying native reprensetation of the type.
- *
- * In addition the value pointed by
- * "conv" will contain the kind of marshalling required for this
- * particular type one of the MONO_MARSHAL_CONV_ enumeration values.
*/
guint32
mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_field,
/**
* mono_type_is_byref:
* \param type the \c MonoType operated on
- *
* \returns TRUE if \p type represents a type passed by reference,
* FALSE otherwise.
*/
/**
* mono_type_get_type:
* \param type the \c MonoType operated on
- * \returns the IL type value for \p type. This is one of the MonoTypeEnum
- * enum members like MONO_TYPE_I4 or MONO_TYPE_STRING.
+ * \returns the IL type value for \p type. This is one of the \c MonoTypeEnum
+ * enum members like \c MONO_TYPE_I4 or \c MONO_TYPE_STRING.
*/
int
mono_type_get_type (MonoType *type)
* mono_type_get_class:
* \param type the \c MonoType operated on
* It is only valid to call this function if \p type is a \c MONO_TYPE_CLASS or a
- * \c MONO_TYPE_VALUETYPE . For more general functionality, use mono_class_from_mono_type(),
+ * \c MONO_TYPE_VALUETYPE . For more general functionality, use \c mono_class_from_mono_type,
* instead.
* \returns the \c MonoClass pointer that describes the class that \p type represents.
*/
return type->data.type;
}
+/**
+ * mono_type_get_modifiers:
+ */
MonoClass*
mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
{
* A \c void* pointer must be initialized to NULL to start the iteration
* and its address is passed to this function repeteadly until it returns
* NULL.
- * \returns: the next parameter type of the method signature \p sig,
+ * \returns the next parameter type of the method signature \p sig,
* NULL when finished.
*/
MonoType*
return owner;
}
+
+void
+mono_loader_set_strict_strong_names (gboolean enabled)
+{
+ check_strong_names_strictly = enabled;
+}
+
+gboolean
+mono_loader_get_strict_strong_names (void)
+{
+ return check_strong_names_strictly;
+}