X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmetadata.c;h=9c082de29c66488f90ab49aa65c04a25338ff2f0;hb=9fa611282112a27d0e804dea300215a7f0cdbdaa;hp=69281fa3a516bd9cb0729e84639a5ad79d717fec;hpb=bbeb09a4428e64ab8e48bf24c272f345f32c698d;p=mono.git diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index 69281fa3a51..9c082de29c6 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -28,6 +28,7 @@ #include "abi-details.h" #include #include +#include /* Auxiliary structure used for caching inflated signatures */ typedef struct { @@ -36,7 +37,7 @@ typedef struct { } MonoInflatedMethodSignature; static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, gboolean transient, - const char *ptr, const char **rptr); + const char *ptr, const char **rptr, MonoError *error); static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only); static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only); @@ -484,6 +485,10 @@ mono_tables_names [] = { #endif +// 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 + /** * mono_meta_table_name: * @table: table index @@ -1318,28 +1323,29 @@ mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *p */ static MonoArrayType * mono_metadata_parse_array_internal (MonoImage *m, MonoGenericContainer *container, - gboolean transient, const char *ptr, const char **rptr) + gboolean transient, const char *ptr, const char **rptr, MonoError *error) { int i; MonoArrayType *array; MonoType *etype; - array = transient ? g_malloc0 (sizeof (MonoArrayType)) : mono_image_alloc0 (m, sizeof (MonoArrayType)); - etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr); + etype = mono_metadata_parse_type_checked (m, container, 0, FALSE, ptr, &ptr, error); //FIXME this doesn't respect @transient if (!etype) return NULL; + + array = transient ? (MonoArrayType *)g_malloc0 (sizeof (MonoArrayType)) : (MonoArrayType *)mono_image_alloc0 (m, sizeof (MonoArrayType)); array->eklass = mono_class_from_mono_type (etype); array->rank = mono_metadata_decode_value (ptr, &ptr); array->numsizes = mono_metadata_decode_value (ptr, &ptr); if (array->numsizes) - array->sizes = transient ? g_malloc0 (sizeof (int) * array->numsizes) : mono_image_alloc0 (m, sizeof (int) * array->numsizes); + array->sizes = transient ? (int *)g_malloc0 (sizeof (int) * array->numsizes) : (int *)mono_image_alloc0 (m, sizeof (int) * array->numsizes); for (i = 0; i < array->numsizes; ++i) array->sizes [i] = mono_metadata_decode_value (ptr, &ptr); array->numlobounds = mono_metadata_decode_value (ptr, &ptr); if (array->numlobounds) - array->lobounds = transient ? g_malloc0 (sizeof (int) * array->numlobounds) : mono_image_alloc0 (m, sizeof (int) * array->numlobounds); + array->lobounds = transient ? (int *)g_malloc0 (sizeof (int) * array->numlobounds) : (int *)mono_image_alloc0 (m, sizeof (int) * array->numlobounds); for (i = 0; i < array->numlobounds; ++i) array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr); @@ -1348,17 +1354,16 @@ mono_metadata_parse_array_internal (MonoImage *m, MonoGenericContainer *containe return array; } -MonoArrayType * -mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container, - const char *ptr, const char **rptr) -{ - return mono_metadata_parse_array_internal (m, container, FALSE, ptr, rptr); -} - MonoArrayType * mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr) { - return mono_metadata_parse_array_full (m, NULL, ptr, rptr); + MonoError error; + MonoArrayType *ret = mono_metadata_parse_array_internal (m, NULL, FALSE, ptr, rptr, &error); + if (!ret) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /*FIXME don't swallow the error message*/ + } + return ret; } /* @@ -1481,10 +1486,14 @@ mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b { int i; -#ifndef MONO_SMALL_CONFIG - if (a->id && b->id) { + // An optimization: if the ids of two insts are the same, we know they are the same inst and don't check contents. + // Furthermore, because we perform early de-duping, if the ids differ, we know the contents differ. +#ifndef MONO_SMALL_CONFIG // Optimization does not work in MONO_SMALL_CONFIG: There are no IDs + if (a->id && b->id) { // "id 0" means "object has no id"-- de-duping hasn't been performed yet, must check contents. if (a->id == b->id) return TRUE; + // In signature-comparison mode id equality implies object equality, but this is not true for inequality. + // Two separate objects could have signature-equavalent contents. if (!signature_only) return FALSE; } @@ -1546,7 +1555,7 @@ mono_metadata_init (void) for (i = 0; i < NBUILTIN_TYPES (); ++i) g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]); - mono_mutex_init_recursive (&image_sets_mutex); + mono_os_mutex_init_recursive (&image_sets_mutex); } /** @@ -1562,7 +1571,7 @@ mono_metadata_cleanup (void) type_cache = NULL; g_ptr_array_free (image_sets, TRUE); image_sets = NULL; - mono_mutex_destroy (&image_sets_mutex); + mono_os_mutex_destroy (&image_sets_mutex); } /** @@ -1591,17 +1600,19 @@ mono_metadata_cleanup (void) * Returns: a #MonoType structure representing the decoded type. */ static MonoType* -mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode, - short opt_attrs, gboolean transient, const char *ptr, const char **rptr) +mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container, + short opt_attrs, gboolean transient, const char *ptr, const char **rptr, MonoError *error) { MonoType *type, *cached; MonoType stype; gboolean byref = FALSE; gboolean pinned = FALSE; const char *tmp_ptr; - int count = 0; + int count = 0; // Number of mod arguments gboolean found; + mono_error_init (error); + /* * According to the spec, custom modifiers should come before the byref * flag, but the IL produced by ilasm from the following signature: @@ -1633,20 +1644,22 @@ mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container } } - if (count) { + if (count) { // There are mods, so the MonoType will be of nonstandard size. int size; size = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod); - type = transient ? g_malloc0 (size) : mono_image_alloc0 (m, size); + type = transient ? (MonoType *)g_malloc0 (size) : (MonoType *)mono_image_alloc0 (m, size); type->num_mods = count; - if (count > 64) - g_warning ("got more than 64 modifiers in type"); - } else { + if (count > 64) { + mono_error_set_bad_image (error, m, "Invalid type with more than 64 modifiers"); + return NULL; + } + } else { // The type is of standard size, so we can allocate it on the stack. type = &stype; memset (type, 0, MONO_SIZEOF_TYPE); } - /* Parse pinned, byref and custom modifiers */ + /* Iterate again, but now parse pinned, byref and custom modifiers */ found = TRUE; count = 0; while (found) { @@ -1673,13 +1686,13 @@ mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container type->byref = byref; type->pinned = pinned ? 1 : 0; - if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr)) { + if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr, error)) return NULL; - } if (rptr) *rptr = ptr; + // Possibly we can return an already-allocated type instead of the one we decoded if (!type->num_mods && !transient) { /* no need to free type here, because it is on the stack */ if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) { @@ -1708,25 +1721,42 @@ mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container } } /* No need to use locking since nobody is modifying the hash table */ - if ((cached = g_hash_table_lookup (type_cache, type))) { + if ((cached = (MonoType *)g_hash_table_lookup (type_cache, type))) { return cached; } } /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */ - if (type == &stype) { - type = transient ? g_malloc (MONO_SIZEOF_TYPE) : mono_image_alloc (m, MONO_SIZEOF_TYPE); + if (type == &stype) { // Type was allocated on the stack, so we need to copy it to safety + type = transient ? (MonoType *)g_malloc (MONO_SIZEOF_TYPE) : (MonoType *)mono_image_alloc (m, MONO_SIZEOF_TYPE); memcpy (type, &stype, MONO_SIZEOF_TYPE); } return type; } + MonoType* -mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode, +mono_metadata_parse_type_checked (MonoImage *m, MonoGenericContainer *container, + short opt_attrs, gboolean transient, const char *ptr, const char **rptr, MonoError *error) +{ + return mono_metadata_parse_type_internal (m, container, opt_attrs, transient, ptr, rptr, error); +} + + +MonoType* +mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, short opt_attrs, const char *ptr, const char **rptr) { - return mono_metadata_parse_type_internal (m, container, mode, opt_attrs, FALSE, ptr, rptr); + MonoError error; + MonoType * type = mono_metadata_parse_type_internal (m, container, opt_attrs, FALSE, ptr, rptr, &error); + mono_loader_assert_no_error (); + if (!mono_error_ok (&error)) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); + } + + return type; } /* @@ -1736,7 +1766,7 @@ MonoType* mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs, const char *ptr, const char **rptr) { - return mono_metadata_parse_type_full (m, NULL, mode, opt_attrs, ptr, rptr); + return mono_metadata_parse_type_full (m, NULL, opt_attrs, ptr, rptr); } gboolean @@ -1823,7 +1853,7 @@ mono_metadata_parse_signature (MonoImage *image, guint32 token) const char *ptr; if (image_is_dynamic (image)) - return mono_lookup_dynamic_token (image, token, NULL); + return (MonoMethodSignature *)mono_lookup_dynamic_token (image, token, NULL); g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG); @@ -1855,7 +1885,7 @@ mono_metadata_signature_alloc (MonoImage *m, guint32 nparams) { MonoMethodSignature *sig; - sig = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_SIGNATURE + ((gint32)nparams) * sizeof (MonoType*)); + sig = (MonoMethodSignature *)mono_image_alloc0 (m, MONO_SIZEOF_METHOD_SIGNATURE + ((gint32)nparams) * sizeof (MonoType*)); sig->param_count = nparams; sig->sentinelpos = -1; @@ -1872,11 +1902,11 @@ mono_metadata_signature_dup_internal_with_padding (MonoImage *image, MonoMemPool sigsize += MONO_SIZEOF_TYPE; if (image) { - ret = mono_image_alloc (image, sigsize); + ret = (MonoMethodSignature *)mono_image_alloc (image, sigsize); } else if (mp) { - ret = mono_mempool_alloc (mp, sigsize); + ret = (MonoMethodSignature *)mono_mempool_alloc (mp, sigsize); } else { - ret = g_malloc (sigsize); + ret = (MonoMethodSignature *)g_malloc (sigsize); } memcpy (ret, sig, sig_header_size - padding); @@ -2018,14 +2048,10 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c method->generic_param_count = gen_param_count; if (call_convention != 0xa) { - method->ret = mono_metadata_parse_type_full (m, container, MONO_PARSE_RET, pattrs ? pattrs [0] : 0, ptr, &ptr); + method->ret = mono_metadata_parse_type_checked (m, container, pattrs ? pattrs [0] : 0, FALSE, ptr, &ptr, error); if (!method->ret) { mono_metadata_free_method_signature (method); g_free (pattrs); - if (mono_loader_get_last_error ()) - mono_error_set_from_loader_error (error); - else - mono_error_set_bad_image (error, m, "Could not parse return type signature"); return NULL; } is_open = mono_class_is_open_constructed_type (method->ret); @@ -2048,12 +2074,8 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c method->sentinelpos = i; ptr++; } - method->params [i] = mono_metadata_parse_type_full (m, container, MONO_PARSE_PARAM, pattrs ? pattrs [i+1] : 0, ptr, &ptr); + method->params [i] = mono_metadata_parse_type_checked (m, container, pattrs ? pattrs [i+1] : 0, FALSE, ptr, &ptr, error); if (!method->params [i]) { - if (mono_loader_get_last_error ()) - mono_error_set_from_loader_error (error); - else - mono_error_set_bad_image (error, m, "Could not parse type argument %d on method signature", i); mono_metadata_free_method_signature (method); g_free (pattrs); return NULL; @@ -2100,13 +2122,16 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c MonoMethodSignature * mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr) { + /* + * This function MUST NOT be called by runtime code as it does error handling incorrectly. + * Use mono_metadata_parse_method_signature_full instead. + * It's ok to asser on failure as we no longer use it. + */ MonoError error; MonoMethodSignature *ret; ret = mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr, &error); - if (!ret) { - mono_loader_set_error_from_mono_error (&error); - mono_error_cleanup (&error); /*FIXME don't swallow the error message*/ - } + g_assert (mono_error_ok (&error)); + return ret; } @@ -2151,8 +2176,8 @@ mono_metadata_free_inflated_signature (MonoMethodSignature *sig) static gboolean inflated_method_equal (gconstpointer a, gconstpointer b) { - const MonoMethodInflated *ma = a; - const MonoMethodInflated *mb = b; + const MonoMethodInflated *ma = (const MonoMethodInflated *)a; + const MonoMethodInflated *mb = (const MonoMethodInflated *)b; if (ma->declaring != mb->declaring) return FALSE; return mono_metadata_generic_context_equal (&ma->context, &mb->context); @@ -2161,15 +2186,15 @@ inflated_method_equal (gconstpointer a, gconstpointer b) static guint inflated_method_hash (gconstpointer a) { - const MonoMethodInflated *ma = a; + const MonoMethodInflated *ma = (const MonoMethodInflated *)a; return (mono_metadata_generic_context_hash (&ma->context) ^ mono_aligned_addr_hash (ma->declaring)); } static gboolean inflated_signature_equal (gconstpointer a, gconstpointer b) { - const MonoInflatedMethodSignature *sig1 = a; - const MonoInflatedMethodSignature *sig2 = b; + const MonoInflatedMethodSignature *sig1 = (const MonoInflatedMethodSignature *)a; + const MonoInflatedMethodSignature *sig2 = (const MonoInflatedMethodSignature *)b; /* sig->sig is assumed to be canonized */ if (sig1->sig != sig2->sig) @@ -2181,7 +2206,7 @@ inflated_signature_equal (gconstpointer a, gconstpointer b) static guint inflated_signature_hash (gconstpointer a) { - const MonoInflatedMethodSignature *sig = a; + const MonoInflatedMethodSignature *sig = (const MonoInflatedMethodSignature *)a; /* sig->sig is assumed to be canonized */ return mono_metadata_generic_context_hash (&sig->context) ^ mono_aligned_addr_hash (sig->sig); @@ -2257,43 +2282,9 @@ retry: goto retry; case MONO_TYPE_FNPTR: return signature_in_image (type->data.method, image); - case MONO_TYPE_VAR: { - MonoGenericContainer *container = mono_type_get_generic_param_owner (type); - if (container) { - g_assert (!container->is_method); - /* - * FIXME: The following check is here solely - * for monodis, which uses the internal - * function - * mono_metadata_load_generic_params(). The - * caller of that function needs to fill in - * owner->klass or owner->method of the - * returned struct, but monodis doesn't do - * that. The image unloading depends on that, - * however, so a crash results without this - * check. - */ - if (!container->owner.klass) - return container->image == image; - return container->owner.klass->image == image; - } else { - return type->data.generic_param->image == image; - } - } - case MONO_TYPE_MVAR: { - MonoGenericContainer *container = mono_type_get_generic_param_owner (type); - if (type->data.generic_param->image == image) - return TRUE; - if (container) { - g_assert (container->is_method); - if (!container->owner.method) - /* RefEmit created generic param whose method is not finished */ - return container->image == image; - return container->owner.method->klass->image == image; - } else { - return type->data.generic_param->image == image; - } - } + case MONO_TYPE_VAR: + case MONO_TYPE_MVAR: + return image == get_image_for_generic_param (type->data.generic_param); default: /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */ return image == mono_class_from_mono_type (type)->image; @@ -2303,13 +2294,13 @@ retry: static inline void image_sets_lock (void) { - mono_mutex_lock (&image_sets_mutex); + mono_os_mutex_lock (&image_sets_mutex); } static inline void image_sets_unlock (void) { - mono_mutex_unlock (&image_sets_mutex); + mono_os_mutex_unlock (&image_sets_mutex); } /* @@ -2324,11 +2315,12 @@ get_image_set (MonoImage **images, int nimages) MonoImageSet *set; GSList *l; - /* Common case */ + /* Common case: Image set contains corlib only. If we've seen that case before, we cached the set. */ if (nimages == 1 && images [0] == mono_defaults.corlib && mscorlib_image_set) return mscorlib_image_set; /* Happens with empty generic instances */ + // FIXME: Is corlib the correct thing to return here? If so, why? This may be an artifact of generic instances previously defaulting to allocating from corlib. if (nimages == 0) return mscorlib_image_set; @@ -2337,43 +2329,51 @@ get_image_set (MonoImage **images, int nimages) if (!image_sets) image_sets = g_ptr_array_new (); + // Before we go on, we should check to see whether a MonoImageSet with these images already exists. + // We can search the referred-by imagesets of any one of our images to do this. Arbitrarily pick one here: if (images [0] == mono_defaults.corlib && nimages > 1) - l = images [1]->image_sets; + l = images [1]->image_sets; // Prefer not to search the imagesets of corlib-- that will be a long list. else l = images [0]->image_sets; set = NULL; - for (; l; l = l->next) { - set = l->data; + while (l) // Iterate over selected list, looking for an imageset with members equal to our target one + { + set = (MonoImageSet *)l->data; - if (set->nimages == nimages) { + if (set->nimages == nimages) { // Member count differs, this can't be it + // Compare all members to all members-- order might be different for (j = 0; j < nimages; ++j) { for (k = 0; k < nimages; ++k) if (set->images [k] == images [j]) - break; + break; // Break on match + + // If we iterated all the way through set->images, images[j] was *not* found. if (k == nimages) - /* Not found */ - break; + 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 if (j == nimages) - /* Found */ - break; + break; // Break on "found a set with equal members" } + + l = l->next; } + // If we iterated all the way through l without breaking, the imageset does not already exist and we shuold create it if (!l) { - /* Not found */ set = g_new0 (MonoImageSet, 1); set->nimages = nimages; set->images = g_new0 (MonoImage*, nimages); - mono_mutex_init_recursive (&set->lock); + 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->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); - + for (i = 0; i < nimages; ++i) set->images [i]->image_sets = g_slist_prepend (set->images [i]->image_sets, set); @@ -2414,20 +2414,20 @@ delete_image_set (MonoImageSet *set) if (set->mempool) mono_mempool_destroy (set->mempool); g_free (set->images); - mono_mutex_destroy (&set->lock); + mono_os_mutex_destroy (&set->lock); g_free (set); } void mono_image_set_lock (MonoImageSet *set) { - mono_mutex_lock (&set->lock); + mono_os_mutex_lock (&set->lock); } void mono_image_set_unlock (MonoImageSet *set) { - mono_mutex_unlock (&set->lock); + mono_os_mutex_unlock (&set->lock); } gpointer @@ -2437,7 +2437,7 @@ mono_image_set_alloc (MonoImageSet *set, guint size) mono_image_set_lock (set); if (!set->mempool) - set->mempool = mono_mempool_new_size (1024); + set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE); res = mono_mempool_alloc (set->mempool, size); mono_image_set_unlock (set); @@ -2451,7 +2451,7 @@ mono_image_set_alloc0 (MonoImageSet *set, guint size) mono_image_set_lock (set); if (!set->mempool) - set->mempool = mono_mempool_new_size (1024); + set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE); res = mono_mempool_alloc0 (set->mempool, size); mono_image_set_unlock (set); @@ -2465,13 +2465,31 @@ mono_image_set_strdup (MonoImageSet *set, const char *s) mono_image_set_lock (set); if (!set->mempool) - set->mempool = mono_mempool_new_size (1024); + set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE); res = mono_mempool_strdup (set->mempool, s); mono_image_set_unlock (set); return res; } +// Get a descriptive string for a MonoImageSet +// Callers are obligated to free buffer with g_free after use +char * +mono_image_set_description (MonoImageSet *set) +{ + GString *result = g_string_new (NULL); + int img; + g_string_append (result, "["); + for (img = 0; img < set->nimages; img++) + { + if (img > 0) + g_string_append (result, ", "); + g_string_append (result, set->images[img]->name); + } + g_string_append (result, "]"); + return g_string_free (result, FALSE); +} + /* * Structure used by the collect_..._images functions to store the image list. */ @@ -2606,48 +2624,13 @@ retry: case MONO_TYPE_FNPTR: //return signature_in_image (type->data.method, image); g_assert_not_reached (); - case MONO_TYPE_VAR: { - MonoGenericContainer *container = mono_type_get_generic_param_owner (type); - if (container) { - g_assert (!container->is_method); - /* - * FIXME: The following check is here solely - * for monodis, which uses the internal - * function - * mono_metadata_load_generic_params(). The - * caller of that function needs to fill in - * owner->klass or owner->method of the - * returned struct, but monodis doesn't do - * that. The image unloading depends on that, - * however, so a crash results without this - * check. - */ - if (!container->owner.klass) - add_image (container->image, data); - else - add_image (container->owner.klass->image, data); - } else { - add_image (type->data.generic_param->image, data); - } - } + case MONO_TYPE_VAR: + case MONO_TYPE_MVAR: + { + MonoImage *image = get_image_for_generic_param (type->data.generic_param); + add_image (image, data); break; - case MONO_TYPE_MVAR: { - MonoGenericContainer *container = mono_type_get_generic_param_owner (type); - if (type->data.generic_param->image) - add_image (type->data.generic_param->image, data); - if (container) { - if (!container->owner.method) { - /* RefEmit created generic param whose method is not finished */ - add_image (container->image, data); - } else { - g_assert (container->is_method); - add_image (container->owner.method->klass->image, data); - } - } else { - add_image (type->data.generic_param->image, data); - } } - break; case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: add_image (mono_class_from_mono_type (type)->image, data); @@ -2665,8 +2648,8 @@ typedef struct { static gboolean steal_gclass_in_image (gpointer key, gpointer value, gpointer data) { - MonoGenericClass *gclass = key; - CleanForImageUserData *user_data = data; + MonoGenericClass *gclass = (MonoGenericClass *)key; + CleanForImageUserData *user_data = (CleanForImageUserData *)data; g_assert (gclass_in_image (gclass, user_data->image)); @@ -2677,8 +2660,8 @@ steal_gclass_in_image (gpointer key, gpointer value, gpointer data) static gboolean steal_ginst_in_image (gpointer key, gpointer value, gpointer data) { - MonoGenericInst *ginst = key; - CleanForImageUserData *user_data = data; + MonoGenericInst *ginst = (MonoGenericInst *)key; + CleanForImageUserData *user_data = (CleanForImageUserData *)data; // This doesn't work during corlib compilation //g_assert (ginst_in_image (ginst, user_data->image)); @@ -2690,8 +2673,8 @@ steal_ginst_in_image (gpointer key, gpointer value, gpointer data) static gboolean inflated_method_in_image (gpointer key, gpointer value, gpointer data) { - MonoImage *image = data; - MonoMethodInflated *method = key; + MonoImage *image = (MonoImage *)data; + MonoMethodInflated *method = (MonoMethodInflated *)key; // FIXME: // https://bugzilla.novell.com/show_bug.cgi?id=458168 @@ -2705,8 +2688,8 @@ inflated_method_in_image (gpointer key, gpointer value, gpointer data) static gboolean inflated_signature_in_image (gpointer key, gpointer value, gpointer data) { - MonoImage *image = data; - MonoInflatedMethodSignature *sig = key; + MonoImage *image = (MonoImage *)data; + MonoInflatedMethodSignature *sig = (MonoInflatedMethodSignature *)key; return signature_in_image (sig->sig, image) || (sig->context.class_inst && ginst_in_image (sig->context.class_inst, image)) || @@ -2716,8 +2699,8 @@ inflated_signature_in_image (gpointer key, gpointer value, gpointer data) static void check_gmethod (gpointer key, gpointer value, gpointer data) { - MonoMethodInflated *method = key; - MonoImage *image = data; + MonoMethodInflated *method = (MonoMethodInflated *)key; + MonoImage *image = (MonoImage *)data; if (method->context.class_inst) g_assert (!ginst_in_image (method->context.class_inst, image)); @@ -2742,7 +2725,7 @@ check_image_sets (MonoImage *image) return; for (i = 0; i < image_sets->len; ++i) { - MonoImageSet *set = g_ptr_array_index (image_sets, i); + MonoImageSet *set = (MonoImageSet *)g_ptr_array_index (image_sets, i); if (!g_slist_find (l, set)) { g_hash_table_foreach (set->gmethod_cache, check_gmethod, image); @@ -2768,7 +2751,7 @@ mono_metadata_clean_for_image (MonoImage *image) /* Collect the items to delete */ /* delete_image_set () modifies the lists so make a copy */ for (l = image->image_sets; l; l = l->next) { - MonoImageSet *set = l->data; + MonoImageSet *set = (MonoImageSet *)l->data; mono_image_set_lock (set); g_hash_table_foreach_steal (set->gclass_cache, steal_gclass_in_image, &gclass_data); @@ -2780,15 +2763,15 @@ mono_metadata_clean_for_image (MonoImage *image) /* Delete the removed items */ for (l = ginst_data.list; l; l = l->next) - free_generic_inst (l->data); + free_generic_inst ((MonoGenericInst *)l->data); for (l = gclass_data.list; l; l = l->next) - free_generic_class (l->data); + free_generic_class ((MonoGenericClass *)l->data); g_slist_free (ginst_data.list); g_slist_free (gclass_data.list); /* delete_image_set () modifies the lists so make a copy */ set_list = g_slist_copy (image->image_sets); for (l = set_list; l; l = l->next) { - MonoImageSet *set = l->data; + MonoImageSet *set = (MonoImageSet *)l->data; delete_image_set (set); } @@ -2874,7 +2857,7 @@ mono_metadata_get_inflated_signature (MonoMethodSignature *sig, MonoGenericConte mono_image_set_lock (set); - res = g_hash_table_lookup (set->gsignature_cache, &helper); + res = (MonoInflatedMethodSignature *)g_hash_table_lookup (set->gsignature_cache, &helper); if (!res) { res = g_new0 (MonoInflatedMethodSignature, 1); res->sig = sig; @@ -2925,7 +2908,7 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv) break; is_open = (i < type_argc); - ginst = g_alloca (size); + ginst = (MonoGenericInst *)g_alloca (size); memset (ginst, 0, sizeof (MonoGenericInst)); ginst->is_open = is_open; ginst->type_argc = type_argc; @@ -2941,9 +2924,9 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv) mono_image_set_lock (set); - ginst = g_hash_table_lookup (set->ginst_cache, ginst); + ginst = (MonoGenericInst *)g_hash_table_lookup (set->ginst_cache, ginst); if (!ginst) { - ginst = mono_image_set_alloc0 (set, size); + ginst = (MonoGenericInst *)mono_image_set_alloc0 (set, size); #ifndef MONO_SMALL_CONFIG ginst->id = ++next_generic_inst_id; #endif @@ -2985,12 +2968,11 @@ mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst MonoImageSet *set; CollectData data; + memset (&helper, 0, sizeof(helper)); // act like g_new0 helper.container_class = container_class; helper.context.class_inst = inst; - helper.context.method_inst = NULL; helper.is_dynamic = is_dynamic; /* We use this in a hash lookup, which does not attempt to downcast the pointer */ helper.is_tb_open = is_tb_open; - helper.cached_class = NULL; collect_data_init (&data); @@ -3002,7 +2984,7 @@ mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst mono_image_set_lock (set); - gclass = g_hash_table_lookup (set->gclass_cache, &helper); + gclass = (MonoGenericClass *)g_hash_table_lookup (set->gclass_cache, &helper); /* A tripwire just to keep us honest */ g_assert (!helper.cached_class); @@ -3075,16 +3057,17 @@ cleanup: MonoGenericInst * mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container, - int count, const char *ptr, const char **rptr) + int count, const char *ptr, const char **rptr, MonoError *error) { MonoType **type_argv; MonoGenericInst *ginst; int i; + mono_error_init (error); type_argv = g_new0 (MonoType*, count); for (i = 0; i < count; i++) { - MonoType *t = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr); + MonoType *t = mono_metadata_parse_type_checked (m, container, 0, FALSE, ptr, &ptr, error); if (!t) { g_free (type_argv); return NULL; @@ -3104,23 +3087,28 @@ mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container, static gboolean do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container, - const char *ptr, const char **rptr) + const char *ptr, const char **rptr, MonoError *error) { MonoGenericInst *inst; MonoClass *gklass; MonoType *gtype; int count; - gtype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr); + mono_error_init (error); + + // XXX how about transient? + gtype = mono_metadata_parse_type_checked (m, NULL, 0, FALSE, ptr, &ptr, error); if (gtype == NULL) return FALSE; gklass = mono_class_from_mono_type (gtype); - if (!gklass->generic_container) + if (!gklass->generic_container) { + mono_error_set_bad_image (error, m, "Generic instance with non-generic definition"); return FALSE; + } count = mono_metadata_decode_value (ptr, &ptr); - inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr); + inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr, error); if (inst == NULL) return FALSE; @@ -3158,7 +3146,36 @@ select_container (MonoGenericContainer *gc, MonoTypeEnum type) return gc; } -/* +MonoGenericContainer * +get_anonymous_container_for_image (MonoImage *image, gboolean is_mvar) +{ + MonoGenericContainer **container_pointer; + if (is_mvar) + container_pointer = &image->anonymous_generic_method_container; + else + container_pointer = &image->anonymous_generic_class_container; + MonoGenericContainer *result = *container_pointer; + + // This container has never been created; make it now. + if (!result) + { + // Note this is never deallocated anywhere-- it exists for the lifetime of the image it's allocated from + result = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer)); + result->owner.image = image; + result->is_anonymous = TRUE; + result->is_small_param = TRUE; + result->is_method = is_mvar; + + // If another thread already made a container, use that and leak this new one. + // (Technically it would currently be safe to just assign instead of CASing.) + MonoGenericContainer *exchange = (MonoGenericContainer *)InterlockedCompareExchangePointer ((volatile gpointer *)container_pointer, result, NULL); + if (exchange) + result = exchange; + } + return result; +} + +/* * mono_metadata_parse_generic_param: * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer; * see mono_metadata_parse_type_full() for details. @@ -3167,27 +3184,46 @@ select_container (MonoGenericContainer *gc, MonoTypeEnum type) */ static MonoGenericParam * mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container, - MonoTypeEnum type, const char *ptr, const char **rptr) + MonoTypeEnum type, const char *ptr, const char **rptr, MonoError *error) { int index = mono_metadata_decode_value (ptr, &ptr); if (rptr) *rptr = ptr; + mono_error_init (error); + generic_container = select_container (generic_container, type); if (!generic_container) { + gboolean is_mvar = FALSE; + switch (type) + { + case MONO_TYPE_VAR: + break; + case MONO_TYPE_MVAR: + is_mvar = TRUE; + break; + default: + g_error ("Cerating generic param object with invalid MonoType"); // This is not a generic param + } + /* Create dummy MonoGenericParam */ MonoGenericParam *param; - param = mono_image_alloc0 (m, sizeof (MonoGenericParam)); + param = (MonoGenericParam *)mono_image_alloc0 (m, sizeof (MonoGenericParam)); param->num = index; - param->image = m; + param->owner = get_anonymous_container_for_image (m, is_mvar); return param; } - if (index >= generic_container->type_argc) + if (index >= generic_container->type_argc) { + mono_error_set_bad_image (error, m, "Invalid generic %s parameter index %d, max index is %d", + generic_container->is_method ? "method" : "type", + index, generic_container->type_argc); return NULL; + } + //This can't return NULL return mono_generic_container_get_param (generic_container, index); } @@ -3207,7 +3243,7 @@ mono_metadata_get_shared_type (MonoType *type) MonoType *cached; /* No need to use locking since nobody is modifying the hash table */ - if ((cached = g_hash_table_lookup (type_cache, type))) + if ((cached = (MonoType *)g_hash_table_lookup (type_cache, type))) return cached; switch (type->type){ @@ -3226,8 +3262,10 @@ mono_metadata_get_shared_type (MonoType *type) } static gboolean -compare_type_literals (int class_type, int type_type) +compare_type_literals (MonoImage *image, int class_type, int type_type, MonoError *error) { + mono_error_init (error); + /* byval_arg.type can be zero if we're decoding a type that references a class been loading. * See mcs/test/gtest-440. and #650936. * FIXME This better be moved to the metadata verifier as it can catch more cases. @@ -3240,8 +3278,13 @@ compare_type_literals (int class_type, int type_type) if (class_type == type_type) return TRUE; - if (type_type == MONO_TYPE_CLASS) - return class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT; + if (type_type == MONO_TYPE_CLASS) { + if (class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT) + return TRUE; + //XXX stringify this argument + mono_error_set_bad_image (error, image, "Expected reference type but got type kind %d", class_type); + return FALSE; + } g_assert (type_type == MONO_TYPE_VALUETYPE); switch (class_type) { @@ -3262,10 +3305,31 @@ compare_type_literals (int class_type, int type_type) case MONO_TYPE_CLASS: return TRUE; default: + //XXX stringify this argument + mono_error_set_bad_image (error, image, "Expected value type but got type kind %d", class_type); return FALSE; } } +static gboolean +verify_var_type_and_container (MonoImage *image, int var_type, MonoGenericContainer *container, MonoError *error) +{ + mono_error_init (error); + if (var_type == MONO_TYPE_MVAR) { + if (!container->is_method) { //MVAR and a method container + mono_error_set_bad_image (error, image, "MVAR parsed in a context without a method container"); + return FALSE; + } + } else { + if (!(!container->is_method || //VAR and class container + (container->is_method && container->parent))) { //VAR and method container with parent + mono_error_set_bad_image (error, image, "VAR parsed in a context without a class container"); + return FALSE; + } + } + return TRUE; +} + /* * do_mono_metadata_parse_type: * @type: MonoType to be filled in with the return value @@ -3289,10 +3353,11 @@ compare_type_literals (int class_type, int type_type) */ static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, - gboolean transient, const char *ptr, const char **rptr) + gboolean transient, const char *ptr, const char **rptr, MonoError *error) { - gboolean ok = TRUE; - type->type = mono_metadata_decode_value (ptr, &ptr); + mono_error_init (error); + + type->type = (MonoTypeEnum)mono_metadata_decode_value (ptr, &ptr); switch (type->type){ case MONO_TYPE_VOID: @@ -3317,68 +3382,69 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer case MONO_TYPE_VALUETYPE: case MONO_TYPE_CLASS: { guint32 token; - MonoClass *class; - MonoError error; + MonoClass *klass; token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr); - class = mono_class_get_checked (m, token, &error); - type->data.klass = class; - if (!class) { - mono_loader_set_error_from_mono_error (&error); - mono_error_cleanup (&error); /*FIXME don't swallow the error message*/ + klass = mono_class_get_checked (m, token, error); + type->data.klass = klass; + if (!klass) return FALSE; - } - if (!compare_type_literals (class->byval_arg.type, type->type)) + + if (!compare_type_literals (m, klass->byval_arg.type, type->type, error)) return FALSE; + break; } case MONO_TYPE_SZARRAY: { - MonoType *etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr); + MonoType *etype = mono_metadata_parse_type_checked (m, container, 0, transient, ptr, &ptr, error); if (!etype) return FALSE; + type->data.klass = mono_class_from_mono_type (etype); - if (!type->data.klass) - return FALSE; + g_assert (type->data.klass); //This was previously a check for NULL, but mcfmt should never fail. It can return a borken MonoClass, but should return at least something. break; } - case MONO_TYPE_PTR: - type->data.type = mono_metadata_parse_type_internal (m, container, MONO_PARSE_MOD_TYPE, 0, transient, ptr, &ptr); + case MONO_TYPE_PTR: { + type->data.type = mono_metadata_parse_type_checked (m, container, 0, transient, ptr, &ptr, error); if (!type->data.type) return FALSE; break; + } case MONO_TYPE_FNPTR: { - MonoError error; - type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr, &error); - if (!type->data.method) { - mono_loader_set_error_from_mono_error (&error); - mono_error_cleanup (&error); /*FIXME don't swallow the error message*/ + type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr, error); + if (!type->data.method) return FALSE; - } break; } - case MONO_TYPE_ARRAY: - type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr); + case MONO_TYPE_ARRAY: { + type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr, error); if (!type->data.array) return FALSE; break; + } case MONO_TYPE_MVAR: - if (container && !container->is_method) + case MONO_TYPE_VAR: { + if (container && !verify_var_type_and_container (m, type->type, container, error)) return FALSE; - case MONO_TYPE_VAR: - type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr); + + type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr, error); if (!type->data.generic_param) return FALSE; + break; - case MONO_TYPE_GENERICINST: - ok = do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr); + } + case MONO_TYPE_GENERICINST: { + if (!do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr, error)) + return FALSE; break; + } default: - g_warning ("type 0x%02x not handled in do_mono_metadata_parse_type on image %s", type->type, m->name); + mono_error_set_bad_image (error, m, "type 0x%02x not handled in do_mono_metadata_parse_type on image %s", type->type, m->name); return FALSE; } if (rptr) *rptr = ptr; - return ok; + return TRUE; } /* @@ -3474,7 +3540,7 @@ parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr) int i; *num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12; /* we could just store a pointer if we don't need to byteswap */ - clauses = g_malloc0 (sizeof (MonoExceptionClause) * (*num_clauses)); + clauses = (MonoExceptionClause *)g_malloc0 (sizeof (MonoExceptionClause) * (*num_clauses)); for (i = 0; i < *num_clauses; ++i) { MonoExceptionClause *ec = &clauses [i]; guint32 tof_value; @@ -3528,7 +3594,7 @@ parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr) * @summary: Where to store the header * * - * Returns: true if the header was properly decoded. + * Returns: TRUE if the header was properly decoded. */ gboolean mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *summary) @@ -3625,7 +3691,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons switch (format) { case METHOD_HEADER_TINY_FORMAT: - mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER); + mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER); ptr++; mh->max_stack = 8; mh->is_transient = TRUE; @@ -3683,16 +3749,21 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons g_warning ("wrong signature for locals blob"); locals_ptr++; len = mono_metadata_decode_value (locals_ptr, &locals_ptr); - mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*) + num_clauses * sizeof (MonoExceptionClause)); + mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*) + num_clauses * sizeof (MonoExceptionClause)); mh->num_locals = len; for (i = 0; i < len; ++i) { - mh->locals [i] = mono_metadata_parse_type_internal (m, container, - MONO_PARSE_LOCAL, 0, TRUE, locals_ptr, &locals_ptr); + MonoError error; + mh->locals [i] = mono_metadata_parse_type_internal (m, container, 0, TRUE, locals_ptr, &locals_ptr, &error); + if (!mono_error_ok (&error)) { + mono_loader_set_error_from_mono_error (&error); + mono_error_cleanup (&error); /* FIXME don't swallow the error */ + } + if (!mh->locals [i]) goto fail; } } else { - mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause)); + mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause)); } mh->code = code; mh->code_size = code_size; @@ -3839,7 +3910,7 @@ mono_method_header_get_clauses (MonoMethodHeader *header, MonoMethod *method, gp *clause = *sc; return TRUE; } - sc = *iter; + sc = (MonoExceptionClause *)*iter; sc++; if (sc < header->clauses + header->num_clauses) { *iter = sc; @@ -4171,7 +4242,7 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono if (heap_alloc_result) result = g_new0 (MonoClass*, pos - start); else - result = mono_image_alloc0 (meta, sizeof (MonoClass*) * (pos - start)); + result = (MonoClass **)mono_image_alloc0 (meta, sizeof (MonoClass*) * (pos - start)); pos = start; while (pos < tdef->rows) { @@ -4476,7 +4547,7 @@ mono_type_size (MonoType *t, int *align) } if (t->byref) { *align = MONO_ABI_ALIGNOF (gpointer); - return sizeof (gpointer); + return MONO_ABI_SIZEOF (gpointer); } simple_type = t->type; @@ -4514,26 +4585,22 @@ mono_type_size (MonoType *t, int *align) case MONO_TYPE_I: case MONO_TYPE_U: *align = MONO_ABI_ALIGNOF (gpointer); - return sizeof (gpointer); - case MONO_TYPE_STRING: - *align = MONO_ABI_ALIGNOF (gpointer); - return sizeof (gpointer); - case MONO_TYPE_OBJECT: - *align = MONO_ABI_ALIGNOF (gpointer); - return sizeof (gpointer); + return MONO_ABI_SIZEOF (gpointer); case MONO_TYPE_VALUETYPE: { if (t->data.klass->enumtype) return mono_type_size (mono_class_enum_basetype (t->data.klass), align); else return mono_class_value_size (t->data.klass, (guint32*)align); } + case MONO_TYPE_STRING: + case MONO_TYPE_OBJECT: case MONO_TYPE_CLASS: case MONO_TYPE_SZARRAY: case MONO_TYPE_PTR: case MONO_TYPE_FNPTR: case MONO_TYPE_ARRAY: *align = MONO_ABI_ALIGNOF (gpointer); - return sizeof (gpointer); + return MONO_ABI_SIZEOF (gpointer); case MONO_TYPE_TYPEDBYREF: return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align); case MONO_TYPE_GENERICINST: { @@ -4549,14 +4616,14 @@ mono_type_size (MonoType *t, int *align) return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align); } else { *align = MONO_ABI_ALIGNOF (gpointer); - return sizeof (gpointer); + return MONO_ABI_SIZEOF (gpointer); } } case MONO_TYPE_VAR: case MONO_TYPE_MVAR: if (!t->data.generic_param->gshared_constraint || t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE) { *align = MONO_ABI_ALIGNOF (gpointer); - return sizeof (gpointer); + return MONO_ABI_SIZEOF (gpointer); } else { /* The gparam can only match types given by gshared_constraint */ return mono_type_size (t->data.generic_param->gshared_constraint, align); @@ -4587,7 +4654,7 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open) int tmp; MonoTypeEnum simple_type; #if SIZEOF_VOID_P == SIZEOF_REGISTER - int stack_slot_size = sizeof (gpointer); + int stack_slot_size = MONO_ABI_SIZEOF (gpointer); int stack_slot_align = MONO_ABI_ALIGNOF (gpointer); #elif SIZEOF_VOID_P < SIZEOF_REGISTER int stack_slot_size = SIZEOF_REGISTER; @@ -4795,7 +4862,7 @@ mono_metadata_type_hash (MonoType *t1) case MONO_TYPE_VALUETYPE: case MONO_TYPE_CLASS: case MONO_TYPE_SZARRAY: { - MonoClass *class = t1->data.klass; + MonoClass *klass = t1->data.klass; /* * Dynamic classes must not be hashed on their type since it can change * during runtime. For example, if we hash a reference type that is @@ -4804,9 +4871,9 @@ mono_metadata_type_hash (MonoType *t1) * This is specially problematic with generic instances since they are * inserted in a bunch of hash tables before been finished. */ - if (image_is_dynamic (class->image)) - return (t1->byref << 6) | mono_metadata_str_hash (class->name); - return ((hash << 5) - hash) ^ mono_metadata_str_hash (class->name); + if (image_is_dynamic (klass->image)) + return (t1->byref << 6) | mono_metadata_str_hash (klass->name); + return ((hash << 5) - hash) ^ mono_metadata_str_hash (klass->name); } case MONO_TYPE_PTR: return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type); @@ -4861,12 +4928,8 @@ mono_metadata_generic_param_equal_internal (MonoGenericParam *p1, MonoGenericPar * image B gets that generic inst from the cache, image A is * unloaded, so the inst is deleted, but image B still retains * a pointer to it. - * - * The AOT runtime doesn't set the image when it's decoding - * types, so we only compare it when the owner is NULL. */ - if (mono_generic_param_owner (p1) == mono_generic_param_owner (p2) && - (mono_generic_param_owner (p1) || p1->image == p2->image)) + if (mono_generic_param_owner (p1) == mono_generic_param_owner (p2)) return TRUE; /* @@ -4944,6 +5007,7 @@ mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gbo * mono_metadata_type_equal: * @t1: a type * @t2: another type + * @signature_only: If true, treat ginsts as equal which are instantiated separately but have equal positional value * * Determine if @t1 and @t2 represent the same type. * Returns: #TRUE if @t1 and @t2 are equal. @@ -5086,7 +5150,7 @@ mono_metadata_type_dup (MonoImage *image, const MonoType *o) if (o->num_mods) sizeof_o += o->num_mods * sizeof (MonoCustomMod); - r = image ? mono_image_alloc0 (image, sizeof_o) : g_malloc (sizeof_o); + r = image ? (MonoType *)mono_image_alloc0 (image, sizeof_o) : (MonoType *)g_malloc (sizeof_o); memcpy (r, o, sizeof_o); @@ -5504,7 +5568,7 @@ mono_type_create_from_typespec_checked (MonoImage *image, guint32 type_spec, Mon mono_error_init (error); mono_image_lock (image); - type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)); + type = (MonoType *)g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)); mono_image_unlock (image); if (type) return type; @@ -5521,20 +5585,15 @@ mono_type_create_from_typespec_checked (MonoImage *image, guint32 type_spec, Mon mono_metadata_decode_value (ptr, &ptr); - type = mono_metadata_parse_type_internal (image, NULL, MONO_PARSE_TYPE, 0, TRUE, ptr, &ptr); - if (!type) { - if (mono_loader_get_last_error ()) - mono_error_set_from_loader_error (error); - else - mono_error_set_bad_image (error, image, "Could not parse type spec %08x.", type_spec); + type = mono_metadata_parse_type_checked (image, NULL, 0, TRUE, ptr, &ptr, error); + if (!type) return NULL; - } type2 = mono_metadata_type_dup (image, type); mono_metadata_free_type (type); mono_image_lock (image); - type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)); + 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); @@ -5552,7 +5611,7 @@ mono_image_strndup (MonoImage *image, const char *data, guint len) char *res; if (!image) return g_strndup (data, len); - res = mono_image_alloc (image, len + 1); + res = (char *)mono_image_alloc (image, len + 1); memcpy (res, data, len); res [len] = 0; return res; @@ -5578,12 +5637,12 @@ mono_metadata_parse_marshal_spec_full (MonoImage *image, MonoImage *parent_image /* fixme: this is incomplete, but I cant find more infos in the specs */ if (image) - res = mono_image_alloc0 (image, sizeof (MonoMarshalSpec)); + res = (MonoMarshalSpec *)mono_image_alloc0 (image, sizeof (MonoMarshalSpec)); else res = g_new0 (MonoMarshalSpec, 1); len = mono_metadata_decode_value (ptr, &ptr); - res->native = *ptr++; + res->native = (MonoMarshalNative)*ptr++; if (res->native == MONO_NATIVE_LPARRAY) { res->data.array_data.param_num = -1; @@ -5591,7 +5650,7 @@ mono_metadata_parse_marshal_spec_full (MonoImage *image, MonoImage *parent_image res->data.array_data.elem_mult = -1; if (ptr - start <= len) - res->data.array_data.elem_type = *ptr++; + res->data.array_data.elem_type = (MonoMarshalNative)*ptr++; if (ptr - start <= len) res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr); if (ptr - start <= len) @@ -5638,10 +5697,10 @@ mono_metadata_parse_marshal_spec_full (MonoImage *image, MonoImage *parent_image } if (res->native == MONO_NATIVE_SAFEARRAY) { - res->data.safearray_data.elem_type = 0; + res->data.safearray_data.elem_type = (MonoMarshalVariant)0; res->data.safearray_data.num_elem = 0; if (ptr - start <= len) - res->data.safearray_data.elem_type = *ptr++; + res->data.safearray_data.elem_type = (MonoMarshalVariant)*ptr++; if (ptr - start <= len) res->data.safearray_data.num_elem = *ptr++; } @@ -6032,9 +6091,9 @@ get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGene } if (!found) return TRUE; - res = mono_image_alloc0 (image, sizeof (MonoClass*) * (found + 1)); + res = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * (found + 1)); for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) { - res [i] = tmp->data; + res [i] = (MonoClass *)tmp->data; } g_slist_free (cons); *constraints = res; @@ -6146,11 +6205,12 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericC mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE); params = NULL; n = 0; - container = mono_image_alloc0 (image, sizeof (MonoGenericContainer)); - container->image = image; + container = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer)); + container->owner.image = image; // Temporarily mark as anonymous, but this will be overriden by caller + container->is_anonymous = TRUE; do { n++; - params = g_realloc (params, sizeof (MonoGenericParamFull) * n); + params = (MonoGenericParamFull *)g_realloc (params, sizeof (MonoGenericParamFull) * n); memset (¶ms [n - 1], 0, sizeof (MonoGenericParamFull)); params [n - 1].param.owner = container; params [n - 1].param.num = cols [MONO_GENERICPARAM_NUMBER]; @@ -6165,7 +6225,7 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericC } while (cols [MONO_GENERICPARAM_OWNER] == owner); container->type_argc = n; - container->type_params = mono_image_alloc0 (image, sizeof (MonoGenericParamFull) * n); + container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (image, sizeof (MonoGenericParamFull) * n); memcpy (container->type_params, params, sizeof (MonoGenericParamFull) * n); g_free (params); container->parent = parent_container; @@ -6415,7 +6475,7 @@ mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter) return NULL; } } - type = *iter; + type = (MonoType **)*iter; type++; if (type < &sig->params [sig->param_count]) { *iter = type; @@ -6573,3 +6633,32 @@ mono_method_get_wrapper_cache (MonoMethod *method) return &method->klass->image->wrapper_caches; } } + +// This is support for the mempool reference tracking feature in checked-build, but lives in metadata.c due to use of static variables of this file. + +/** + * mono_find_image_set_owner: + * + * Find the imageset, if any, which a given pointer is located in the memory of. + */ +MonoImageSet * +mono_find_image_set_owner (void *ptr) +{ + MonoImageSet *owner = NULL; + int i; + + image_sets_lock (); + + if (image_sets) + { + for (i = 0; !owner && i < image_sets->len; ++i) { + MonoImageSet *set = (MonoImageSet *)g_ptr_array_index (image_sets, i); + if (mono_mempool_contains_addr (set->mempool, ptr)) + owner = set; + } + } + + image_sets_unlock (); + + return owner; +}