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)
{
{
int i;
+#ifndef MONO_SMALL_CONFIG
if (a->id && b->id) {
if (a->id == b->id)
return TRUE;
if (!signature_only)
return FALSE;
}
+#endif
if (a->is_open != b->is_open || a->type_argc != b->type_argc)
return FALSE;
* @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.
*/
mono_metadata_free_inflated_signature (method->signature);
if (!((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))) {
- MonoMethodNormal* mn = (MonoMethodNormal*) method;
- MonoMethodHeader *header = mn->header;
+ MonoMethodHeader *header = imethod->header;
if (header) {
/* Allocated in inflate_generic_header () */
/* 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;
is_open = (i < type_argc);
ginst = alloca (size);
+#ifndef MONO_SMALL_CONFIG
ginst->id = 0;
+#endif
ginst->is_open = is_open;
ginst->type_argc = type_argc;
memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
ginst = g_hash_table_lookup (set->ginst_cache, ginst);
if (!ginst) {
ginst = g_malloc (size);
+#ifndef MONO_SMALL_CONFIG
ginst->id = ++next_generic_inst_id;
+#endif
ginst->is_open = is_open;
ginst->type_argc = type_argc;
/*
* 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;
#endif
/**
- * @mh: The Method header
* @ptr: Points to the beginning of the Section Data (25.3)
*/
-static void
-parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr)
+static MonoExceptionClause*
+parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr)
{
unsigned char sect_data_flags;
const unsigned char *sptr;
int is_fat;
guint32 sect_data_len;
+ MonoExceptionClause* clauses = NULL;
while (1) {
/* align on 32-bit boundary */
if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
const unsigned char *p = dword_align (ptr);
int i;
- mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
+ *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 */
- mh->clauses = mono_image_alloc0 (m, sizeof (MonoExceptionClause) * mh->num_clauses);
- for (i = 0; i < mh->num_clauses; ++i) {
- MonoExceptionClause *ec = &mh->clauses [i];
+ clauses = g_malloc0 (sizeof (MonoExceptionClause) * (*num_clauses));
+ for (i = 0; i < *num_clauses; ++i) {
+ MonoExceptionClause *ec = &clauses [i];
guint32 tof_value;
if (is_fat) {
ec->flags = read32 (p);
if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
else
- return;
+ return clauses;
}
}
if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
return FALSE;
- if (method->klass->image->dynamic || ((MonoMethodNormal*) method)->header) {
- MonoMethodHeader *header = mono_method_get_header (method);
+ if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) {
+ MonoMethodHeader *header = ((MonoMethodWrapper *)method)->header;
if (!header)
return FALSE;
summary->code_size = header->code_size;
*
* 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)
guint16 fat_flags;
guint32 local_var_sig_tok, max_stack, code_size, init_locals;
const unsigned char *code;
- int hsize;
-
+ MonoExceptionClause* clauses = NULL;
+ int hsize, num_clauses = 0;
+ MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
+ guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
+
g_return_val_if_fail (ptr != NULL, NULL);
switch (format) {
case METHOD_HEADER_TINY_FORMAT:
- mh = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER);
+ mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER);
ptr++;
mh->max_stack = 8;
+ mh->is_transient = TRUE;
local_var_sig_tok = 0;
mh->code_size = flags >> 2;
mh->code = (unsigned char*)ptr;
default:
return NULL;
}
-
- if (local_var_sig_tok) {
- MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
- const char *locals_ptr;
- guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
- int len=0, i, bsize;
- mono_metadata_decode_row (t, (local_var_sig_tok & 0xffffff)-1, cols, 1);
+ if (local_var_sig_tok) {
+ int idx = (local_var_sig_tok & 0xffffff)-1;
+ if (idx >= t->rows)
+ return NULL;
+ mono_metadata_decode_row (t, idx, cols, 1);
if (!mono_verifier_verify_standalone_signature (m, cols [MONO_STAND_ALONE_SIGNATURE], NULL))
return NULL;
+ }
+ if (fat_flags & METHOD_HEADER_MORE_SECTS)
+ clauses = parse_section_data (m, &num_clauses, (const unsigned char*)ptr);
+ if (local_var_sig_tok) {
+ const char *locals_ptr;
+ int len=0, i, bsize;
locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
bsize = mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
g_warning ("wrong signature for locals blob");
locals_ptr++;
len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
- mh = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*));
+ 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;
}
}
} else {
- mh = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER);
+ mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause));
}
mh->code = code;
mh->code_size = code_size;
mh->max_stack = max_stack;
+ mh->is_transient = TRUE;
mh->init_locals = init_locals;
- if (fat_flags & METHOD_HEADER_MORE_SECTS)
- parse_section_data (m, mh, (const unsigned char*)ptr);
+ if (clauses) {
+ MonoExceptionClause* clausesp = (MonoExceptionClause*)&mh->locals [mh->num_locals];
+ memcpy (clausesp, clauses, num_clauses * sizeof (MonoExceptionClause));
+ g_free (clauses);
+ mh->clauses = clausesp;
+ mh->num_clauses = num_clauses;
+ }
return mh;
}
* @mh: a method header
*
* Free the memory allocated for the method header.
- * This is a Mono runtime internal function.
*/
void
mono_metadata_free_mh (MonoMethodHeader *mh)
{
- /* Allocated from the mempool */
+ 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) {
+ 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;
}