#include "verify-internals.h"
#include "class.h"
#include "marshal.h"
-#include "gc-internal.h"
+#include "debug-helpers.h"
#include <mono/utils/mono-error-internals.h>
/* Auxiliary structure used for caching inflated signatures */
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);
static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
gboolean signature_only);
-static GSList* free_generic_inst_dependents (MonoGenericInst *ginst);
static void free_generic_inst (MonoGenericInst *ginst);
-static GSList* free_generic_class_dependents (MonoGenericClass *ginst);
static void free_generic_class (MonoGenericClass *ginst);
static void free_inflated_method (MonoMethodInflated *method);
static void free_inflated_signature (MonoInflatedMethodSignature *sig);
const char *data;
g_assert (idx < t->rows);
+ g_assert (idx >= 0);
data = t->base + idx * t->row_size;
g_assert (res_size == count);
}
/*
- * 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)
{
static GHashTable *type_cache = NULL;
static int next_generic_inst_id = 0;
+static MonoImageSet *mscorlib_image_set;
+static GPtrArray *image_sets;
+
static guint mono_generic_class_hash (gconstpointer data);
/*
{
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;
{
g_hash_table_destroy (type_cache);
type_cache = NULL;
+ g_ptr_array_free (image_sets, TRUE);
+ image_sets = NULL;
}
/**
* @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.
*/
}
}
-static MonoImageSet *mscorlib_image_set;
-static GPtrArray *image_sets;
-
/*
* get_image_set:
*
g_free (set);
}
+static void
+mono_image_set_lock (MonoImageSet *set)
+{
+ EnterCriticalSection (&set->lock);
+}
+
+static void
+mono_image_set_unlock (MonoImageSet *set)
+{
+ LeaveCriticalSection (&set->lock);
+}
+
+gpointer
+mono_image_set_alloc (MonoImageSet *set, guint size)
+{
+ gpointer res;
+
+ mono_image_set_lock (set);
+ if (!set->mempool)
+ set->mempool = mono_mempool_new_size (1024);
+ res = mono_mempool_alloc (set->mempool, size);
+ mono_image_set_unlock (set);
+
+ return res;
+}
+
+gpointer
+mono_image_set_alloc0 (MonoImageSet *set, guint size)
+{
+ gpointer res;
+
+ mono_image_set_lock (set);
+ if (!set->mempool)
+ set->mempool = mono_mempool_new_size (1024);
+ res = mono_mempool_alloc0 (set->mempool, size);
+ mono_image_set_unlock (set);
+
+ return res;
+}
+
+char*
+mono_image_set_strdup (MonoImageSet *set, const char *s)
+{
+ char *res;
+
+ mono_image_set_lock (set);
+ if (!set->mempool)
+ set->mempool = mono_mempool_new_size (1024);
+ res = mono_mempool_strdup (set->mempool, s);
+ mono_image_set_unlock (set);
+
+ return res;
+}
+
/*
* Structure used by the collect_..._images functions to store the image list.
*/
//check_image_sets (image);
- /* The data structures could reference each other so we delete them in two phases */
+ /*
+ * The data structures could reference each other so we delete them in two phases.
+ * This is required because of the hashing functions in gclass/ginst_cache.
+ */
ginst_data.image = gclass_data.image = image;
ginst_data.list = gclass_data.list = NULL;
mono_loader_lock ();
/* Delete the removed items */
for (l = ginst_data.list; l; l = l->next)
- free_list = g_slist_concat (free_generic_inst_dependents (l->data), free_list);
+ free_generic_inst (l->data);
for (l = gclass_data.list; l; l = l->next)
- free_list = g_slist_concat (free_generic_class_dependents (l->data), free_list);
+ free_generic_class (l->data);
g_slist_free (ginst_data.list);
g_slist_free (gclass_data.list);
- mono_class_unregister_image_generic_subclasses (image);
/* 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) {
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 () */
}
static void
-free_list_with_data (GSList *l)
-{
- while (l) {
- g_free (l->data);
- l = g_slist_delete_link (l, l);
- }
-}
-
-static GSList*
-free_generic_inst_dependents (MonoGenericInst *ginst)
+free_generic_inst (MonoGenericInst *ginst)
{
int i;
+ /* The ginst itself is allocated from the image set mempool */
for (i = 0; i < ginst->type_argc; ++i)
mono_metadata_free_type (ginst->type_argv [i]);
- return g_slist_prepend (NULL, ginst);
-}
-
-static void
-free_generic_inst (MonoGenericInst *ginst)
-{
- free_list_with_data (free_generic_inst_dependents (ginst));
-}
-
-static GSList*
-free_generic_class_dependents (MonoGenericClass *gclass)
-{
- GSList *l = NULL;
- int i;
-
- /* FIXME: The dynamic case */
- if (gclass->cached_class && !gclass->cached_class->image->dynamic && !mono_generic_class_is_generic_type_definition (gclass)) {
- MonoClass *class = gclass->cached_class;
-
- /* Allocated in mono_class_init () */
- g_free (class->methods);
- if (class->ext)
- g_free (class->ext->properties);
- /* Allocated in mono_generic_class_get_class () */
- g_free (class->interfaces);
- l = g_slist_prepend (l, class);
- } else if (gclass->is_dynamic) {
- MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *)gclass;
-
- for (i = 0; i < dgclass->count_fields; ++i) {
- MonoClassField *field = dgclass->fields + i;
- mono_metadata_free_type (field->type);
- g_free ((char*)field->name);
-#if HAVE_SGEN_GC
- MONO_GC_UNREGISTER_ROOT (dgclass->field_objects [i]);
-#endif
- }
-
- g_free (dgclass->methods);
- g_free (dgclass->ctors);
- g_free (dgclass->fields);
- g_free (dgclass->field_objects);
- g_free (dgclass->field_generic_types);
- if (!mono_generic_class_is_generic_type_definition (gclass))
- l = g_slist_prepend (l, gclass->cached_class);
- }
- return g_slist_prepend (l, gclass);
}
static void
free_generic_class (MonoGenericClass *gclass)
{
- free_list_with_data (free_generic_class_dependents (gclass));
+ /* The gclass itself is allocated from the image set mempool */
+ if (gclass->is_dynamic)
+ mono_reflection_free_dynamic_generic_class (gclass);
}
static void
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);
+ ginst = mono_image_set_alloc0 (set, size);
+#ifndef MONO_SMALL_CONFIG
ginst->id = ++next_generic_inst_id;
+#endif
ginst->is_open = is_open;
ginst->type_argc = type_argc;
}
if (is_dynamic) {
- MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
+ MonoDynamicGenericClass *dgclass = mono_image_set_new0 (set, MonoDynamicGenericClass, 1);
gclass = &dgclass->generic_class;
gclass->is_dynamic = 1;
} else {
- gclass = g_new0 (MonoGenericClass, 1);
+ gclass = mono_image_set_new0 (set, MonoGenericClass, 1);
}
gclass->is_tb_open = is_tb_open;
gclass->container_class = container_class;
gclass->context.class_inst = inst;
gclass->context.method_inst = NULL;
+ gclass->owner = set;
if (inst == container_class->generic_container->context.class_inst && !is_tb_open)
gclass->cached_class = container_class;
/*
* 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);
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS: {
guint32 token;
+ MonoClass *class;
token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
- type->data.klass = mono_class_get (m, token);
- if (!type->data.klass)
+ class = mono_class_get (m, token);
+ type->data.klass = class;
+ if (!class)
+ return FALSE;
+ /* 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.
+ */
+ if (class->byval_arg.type && class->byval_arg.type != type->type)
return FALSE;
break;
}
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 || idx < 0)
+ 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:
const char *ptr;
guint32 len;
MonoType *type, *type2;
- MonoType stack_type;
mono_loader_lock ();
len = mono_metadata_decode_value (ptr, &ptr);
- type = &stack_type;
- memset (type, 0, MONO_SIZEOF_TYPE);
-
- if (*ptr == MONO_TYPE_BYREF) {
- type->byref = 1;
- ptr++;
- }
-
- if (!do_mono_metadata_parse_type (type, image, NULL, ptr, &ptr)) {
+ type = mono_metadata_parse_type_internal (image, NULL, MONO_PARSE_TYPE, 0, TRUE, ptr, &ptr);
+ if (!type) {
mono_loader_unlock ();
return NULL;
}
return type2;
}
- type2 = mono_image_alloc (image, MONO_SIZEOF_TYPE);
- memcpy (type2, type, MONO_SIZEOF_TYPE);
+ type2 = mono_metadata_type_dup (image, type);
g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
+ mono_metadata_free_type (type);
mono_loader_unlock ();
}
*conv = MONO_MARSHAL_CONV_BOOL_I4;
return MONO_NATIVE_BOOLEAN;
- case MONO_TYPE_CHAR: return MONO_NATIVE_U2;
+ case MONO_TYPE_CHAR:
+ if (mspec) {
+ switch (mspec->native) {
+ case MONO_NATIVE_U2:
+ case MONO_NATIVE_U1:
+ return mspec->native;
+ default:
+ g_error ("cant marshal char to native type %02x", mspec->native);
+ }
+ }
+ return unicode ? MONO_NATIVE_U2 : MONO_NATIVE_U1;
case MONO_TYPE_I1: return MONO_NATIVE_I1;
case MONO_TYPE_U1: return MONO_NATIVE_U1;
case MONO_TYPE_I2: return MONO_NATIVE_I2;
return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
}
-static MonoMethod*
+MonoMethod*
method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
{
guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides,
MonoGenericContext *generic_context)
{
+ MonoError error;
locator_t loc;
MonoTableInfo *tdef = &image->tables [MONO_TABLE_METHODIMPL];
guint32 start, end;
for (i = 0; i < num; ++i) {
MonoMethod *method;
+ if (!mono_verifier_verify_methodimpl_row (image, start + i, &error)) {
+ mono_error_cleanup (&error);
+ ok = FALSE;
+ break;
+ }
+
mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
method = method_from_method_def_or_ref (
image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
}
if (!found)
return TRUE;
- res = g_new0 (MonoClass*, found + 1);
+ res = mono_image_alloc0 (image, sizeof (MonoClass*) * (found + 1));
for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
res [i] = tmp->data;
}
return mono_metadata_get_generic_param_row (image, token, &owner);
}
+/*
+ * Memory is allocated from IMAGE's mempool.
+ */
gboolean
mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 token,
MonoGenericContainer *container)
* Load the generic parameter constraints for the newly created generic type or method
* represented by @token and @container. The @container is the new container which has
* been returned by a call to mono_metadata_load_generic_params() with this @token.
+ * Memory is allocated from IMAGE's mempool.
*/
void
mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,
return NULL;
}
+/**
+ * mono_type_is_struct:
+ * @type: the MonoType operated on
+ *
+ * Returns: #TRUE is @type is a struct, that is a ValueType but not en enum
+ * or a basic type like System.Int32. #FALSE otherwise.
+ */
+mono_bool
+mono_type_is_struct (MonoType *type)
+{
+ return (!type->byref && ((type->type == MONO_TYPE_VALUETYPE &&
+ !type->data.klass->enumtype) || (type->type == MONO_TYPE_TYPEDBYREF) ||
+ ((type->type == MONO_TYPE_GENERICINST) &&
+ mono_metadata_generic_class_is_valuetype (type->data.generic_class) &&
+ !type->data.generic_class->container_class->enumtype)));
+}
+
+/**
+ * mono_type_is_void:
+ * @type: the MonoType operated on
+ *
+ * Returns: #TRUE is @type is System.Void. #FALSE otherwise.
+ */
+mono_bool
+mono_type_is_void (MonoType *type)
+{
+ return (type && (type->type == MONO_TYPE_VOID) && !type->byref);
+}
+
+/**
+ * mono_type_is_pointer:
+ * @type: the MonoType operated on
+ *
+ * Returns: #TRUE is @type is a managed or unmanaged pointer type. #FALSE otherwise.
+ */
+mono_bool
+mono_type_is_pointer (MonoType *type)
+{
+ return (type && ((type->byref || (type->type == MONO_TYPE_I) || type->type == MONO_TYPE_STRING)
+ || (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
+ (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_OBJECT) ||
+ (type->type == MONO_TYPE_ARRAY) || (type->type == MONO_TYPE_PTR) ||
+ (type->type == MONO_TYPE_FNPTR)));
+}
+
+/**
+ * mono_type_is_reference:
+ * @type: the MonoType operated on
+ *
+ * Returns: #TRUE is @type represents an object reference . #FALSE otherwise.
+ */
+mono_bool
+mono_type_is_reference (MonoType *type)
+{
+ return (type && (((type->type == MONO_TYPE_STRING) ||
+ (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
+ (type->type == MONO_TYPE_OBJECT) || (type->type == MONO_TYPE_ARRAY)) ||
+ ((type->type == MONO_TYPE_GENERICINST) &&
+ !mono_metadata_generic_class_is_valuetype (type->data.generic_class))));
+}
+
+/**
+ * mono_signature_get_return_type:
+ * @sig: the method signature inspected
+ *
+ * Returns: the return type of the method signature @sig
+ */
MonoType*
mono_signature_get_return_type (MonoMethodSignature *sig)
{
return sig->ret;
}
+/**
+ * mono_signature_get_params:
+ * @sig: the method signature inspected
+ * #iter: pointer to an iterator
+ *
+ * Iterates over the parameters for the method signature @sig.
+ * A void* pointer must be initualized to #NULL to start the iteration
+ * and it's address is passed to this function repeteadly until it returns
+ * #NULL.
+ *
+ * Returns: the next parameter type of the method signature @sig,
+ * #NULL when finished.
+ */
MonoType*
mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
{
return NULL;
}
+/**
+ * mono_signature_get_param_count:
+ * @sig: the method signature inspected
+ *
+ * Returns: the number of parameters in the method signature @sig.
+ */
guint32
mono_signature_get_param_count (MonoMethodSignature *sig)
{
return sig->param_count;
}
+/**
+ * mono_signature_get_call_conv:
+ * @sig: the method signature inspected
+ *
+ * Returns: the call convention of the method signature @sig.
+ */
guint32
mono_signature_get_call_conv (MonoMethodSignature *sig)
{
return sig->call_convention;
}
+/**
+ * mono_signature_vararg_start:
+ * @sig: the method signature inspected
+ *
+ * Returns: the number of the first vararg parameter in the
+ * method signature @sig. -1 if this is not a vararg signature.
+ */
int
mono_signature_vararg_start (MonoMethodSignature *sig)
{
return sig->sentinelpos;
}
+/**
+ * mono_signature_is_instance:
+ * @sig: the method signature inspected
+ *
+ * Returns: #TRUE if this the method signature @sig has an implicit
+ * first instance argument. #FALSE otherwise.
+ */
gboolean
mono_signature_is_instance (MonoMethodSignature *sig)
{
return sig->hasthis;
}
+/**
+ * mono_signature_explicit_this:
+ * @sig: the method signature inspected
+ *
+ * Returns: #TRUE if this the method signature @sig has an explicit
+ * instance argument. #FALSE otherwise.
+ */
gboolean
mono_signature_explicit_this (MonoMethodSignature *sig)
{