MonoGenericContext context;
} MonoInflatedMethodSignature;
-static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
+static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, gboolean transient,
const char *ptr, const char **rptr);
static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
}
/*
- * mono_metadata_parse_array_full:
+ * mono_metadata_parse_array_internal:
* @m: a metadata context.
+ * @transient: whenever to allocate data from the heap
* @ptr: a pointer to an encoded array description.
* @rptr: pointer updated to match the end of the decoded stream
*
* Decodes the compressed array description found in the metadata @m at @ptr.
*
* Returns: a #MonoArrayType structure describing the array type
- * and dimensions. Memory is allocated from the image mempool.
+ * and dimensions. Memory is allocated from the heap or from the image mempool, depending
+ * on the value of @transient.
*
* LOCKING: Acquires the loader lock
*/
-MonoArrayType *
-mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container,
- const char *ptr, const char **rptr)
+static MonoArrayType *
+mono_metadata_parse_array_internal (MonoImage *m, MonoGenericContainer *container,
+ gboolean transient, const char *ptr, const char **rptr)
{
int i;
MonoArrayType *array;
MonoType *etype;
- array = mono_image_alloc0 (m, sizeof (MonoArrayType));
+ 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);
if (!etype)
return NULL;
array->numsizes = mono_metadata_decode_value (ptr, &ptr);
if (array->numsizes)
- array->sizes = mono_image_alloc0 (m, sizeof (int) * array->numsizes);
+ array->sizes = transient ? g_malloc0 (sizeof (int) * array->numsizes) : 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 = mono_image_alloc0 (m, sizeof (int) * array->numlobounds);
+ array->lobounds = transient ? g_malloc0 (sizeof (int) * array->numlobounds) : 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);
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)
{
* @opt_attrs: optional attributes to store in the returned type
* @ptr: pointer to the type representation
* @rptr: pointer updated to match the end of the decoded stream
+ * @transient: whenever to allocate the result from the heap or from a mempool
*
* Decode a compressed type description found at @ptr in @m.
* @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
*
* To parse a generic type, `generic_container' points to the current class'es
* (the `generic_container' field in the MonoClass) or the current generic method's
- * (the `generic_container' field in the MonoMethodNormal) generic container.
+ * (stored in image->property_hash) generic container.
* When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
* this MonoGenericContainer.
- * This is a Mono runtime internal function.
*
* LOCKING: Acquires the loader lock.
*
* Returns: a #MonoType structure representing the decoded type.
*/
-MonoType*
-mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
- short opt_attrs, const char *ptr, const char **rptr)
+static MonoType*
+mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
+ short opt_attrs, gboolean transient, const char *ptr, const char **rptr)
{
MonoType *type, *cached;
MonoType stype;
}
if (count) {
- type = mono_image_alloc0 (m, MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod));
+ int size;
+
+ size = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
+ type = transient ? g_malloc0 (size) : mono_image_alloc0 (m, size);
type->num_mods = count;
if (count > 64)
g_warning ("got more than 64 modifiers in type");
type->byref = byref;
type->pinned = pinned ? 1 : 0;
- if (!do_mono_metadata_parse_type (type, m, container, ptr, &ptr)) {
+ if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr)) {
return NULL;
}
if (rptr)
*rptr = ptr;
- if (!type->num_mods) {
+ 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) {
MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
/* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
if (type == &stype) {
- type = mono_image_alloc (m, MONO_SIZEOF_TYPE);
+ type = transient ? g_malloc (MONO_SIZEOF_TYPE) : 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,
+ short opt_attrs, const char *ptr, const char **rptr)
+{
+ return mono_metadata_parse_type_internal (m, container, mode, opt_attrs, FALSE, ptr, rptr);
+}
+
/*
* LOCKING: Acquires the loader lock.
*/
/* Allocated in mono_class_init () */
g_free (class->methods);
- if (class->ext)
+ if (class->ext) {
g_free (class->ext->properties);
+ g_free (class->ext->field_def_values);
+ }
+ /* Allocated in mono_class_setup_fields () */
+ g_free (class->fields);
+ /* Allocated in mono_class_setup_vtable_general () */
+ g_free (class->vtable);
/* Allocated in mono_generic_class_get_class () */
g_free (class->interfaces);
+ /* Allocated in setup_interface_offsets () */
+ g_free (class->interfaces_packed);
+ g_free (class->interface_offsets_packed);
+ g_free (class->interface_bitmap);
+ /* Allocated in mono_class_setup_supertypes () */
+ g_free (class->supertypes);
l = g_slist_prepend (l, class);
} else if (gclass->is_dynamic) {
MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *)gclass;
/*
* mono_metadata_parse_generic_param:
- * @generic_container: Our MonoClass's or MonoMethodNormal's MonoGenericContainer;
+ * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
* see mono_metadata_parse_type_full() for details.
* Internal routine to parse a generic type parameter.
* LOCKING: Acquires the loader lock
* @type: MonoType to be filled in with the return value
* @m: image context
* @generic_context: generics_context
+ * @transient: whenever to allocate data from the heap
* @ptr: pointer to the encoded type
* @rptr: pointer where the end of the encoded type is saved
*
*/
static gboolean
do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
- const char *ptr, const char **rptr)
+ gboolean transient, const char *ptr, const char **rptr)
{
gboolean ok = TRUE;
type->type = mono_metadata_decode_value (ptr, &ptr);
break;
}
case MONO_TYPE_PTR:
- type->data.type = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+ type->data.type = mono_metadata_parse_type_internal (m, container, MONO_PARSE_MOD_TYPE, 0, transient, ptr, &ptr);
if (!type->data.type)
return FALSE;
break;
return FALSE;
break;
case MONO_TYPE_ARRAY:
- type->data.array = mono_metadata_parse_array_full (m, container, ptr, &ptr);
+ type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr);
if (!type->data.array)
return FALSE;
break;
*
* LOCKING: Acquires the loader lock.
*
- * Returns: a MonoMethodHeader allocated from the image mempool.
+ * Returns: a transient MonoMethodHeader allocated from the heap.
*/
MonoMethodHeader *
mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr)
mh = 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_full (
- m, container, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
+ mh->locals [i] = mono_metadata_parse_type_internal (m, container,
+ MONO_PARSE_LOCAL, 0, TRUE, locals_ptr, &locals_ptr);
if (!mh->locals [i]) {
g_free (clauses);
+ g_free (mh);
return NULL;
}
}
void
mono_metadata_free_mh (MonoMethodHeader *mh)
{
+ int i;
+
/* If it is not transient it means it's part of a wrapper method,
* or a SRE-generated method, so the lifetime in that case is
* dictated by the method's own lifetime
*/
- if (mh->is_transient)
+ if (mh->is_transient) {
+ for (i = 0; i < mh->num_locals; ++i)
+ mono_metadata_free_type (mh->locals [i]);
g_free (mh);
+ }
}
/*
switch (t1->type) {
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS:
- case MONO_TYPE_SZARRAY:
- /* check if the distribution is good enough */
- return ((hash << 5) - hash) ^ mono_metadata_str_hash (t1->data.klass->name);
+ case MONO_TYPE_SZARRAY: {
+ MonoClass *class = 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
+ * later made into a valuetype.
+ *
+ * This is specially problematic with generic instances since they are
+ * inserted in a bunch of hash tables before been finished.
+ */
+ if (class->image->dynamic)
+ return (t1->byref << 6) | mono_metadata_str_hash (class->name);
+ return ((hash << 5) - hash) ^ mono_metadata_str_hash (class->name);
+ }
case MONO_TYPE_PTR:
return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
case MONO_TYPE_ARRAY:
ptr++;
}
- if (!do_mono_metadata_parse_type (type, image, NULL, ptr, &ptr)) {
+ if (!do_mono_metadata_parse_type (type, image, NULL, FALSE, ptr, &ptr)) {
mono_loader_unlock ();
return NULL;
}