[xbuild] Add new reserved properties $(MSBuildThisFile*).
[mono.git] / mono / metadata / metadata.c
index caebbd361cfe3d357390bb6ee2fc0eee3ae91101..40755496fc510abe09f54a94b00ebece95b9c88d 100644 (file)
@@ -10,9 +10,6 @@
  */
 
 #include <config.h>
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -27,7 +24,7 @@
 #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 */
@@ -36,7 +33,7 @@ typedef struct {
        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);
@@ -44,9 +41,7 @@ static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolea
 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);
@@ -963,6 +958,7 @@ mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res
        const char *data;
 
        g_assert (idx < t->rows);
+       g_assert (idx >= 0);
        data = t->base + idx * t->row_size;
        
        g_assert (res_size == count);
@@ -1245,27 +1241,29 @@ mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *p
 }
 
 /*
- * 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;
@@ -1274,13 +1272,13 @@ mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container,
 
        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);
 
@@ -1289,6 +1287,13 @@ mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container,
        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)
 {
@@ -1362,6 +1367,9 @@ builtin_types[] = {
 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);
 
 /*
@@ -1409,12 +1417,14 @@ mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b
 {
        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;
@@ -1484,6 +1494,8 @@ mono_metadata_cleanup (void)
 {
        g_hash_table_destroy (type_cache);
        type_cache = NULL;
+       g_ptr_array_free (image_sets, TRUE);
+       image_sets = NULL;
 }
 
 /**
@@ -1493,6 +1505,7 @@ mono_metadata_cleanup (void)
  * @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,
@@ -1502,18 +1515,17 @@ mono_metadata_cleanup (void)
  *
  * 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;
@@ -1555,7 +1567,10 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
        }
 
        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");
@@ -1591,14 +1606,14 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
        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;
@@ -1634,12 +1649,19 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
        /* 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.
  */
@@ -2156,9 +2178,6 @@ retry:
        }
 }
 
-static MonoImageSet *mscorlib_image_set;
-static GPtrArray *image_sets;
-
 /*
  * get_image_set:
  *
@@ -2255,6 +2274,60 @@ delete_image_set (MonoImageSet *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.
  */
@@ -2538,7 +2611,10 @@ mono_metadata_clean_for_image (MonoImage *image)
 
        //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 ();
@@ -2556,12 +2632,11 @@ mono_metadata_clean_for_image (MonoImage *image)
 
        /* 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) {
@@ -2588,8 +2663,7 @@ free_inflated_method (MonoMethodInflated *imethod)
                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 () */
@@ -2604,74 +2678,21 @@ free_inflated_method (MonoMethodInflated *imethod)
 }
 
 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
@@ -2771,8 +2792,8 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
                        break;
        is_open = (i < type_argc);
 
-       ginst = alloca (size);
-       ginst->id = 0;
+       ginst = g_alloca (size);
+       memset (ginst, 0, sizeof (MonoGenericInst));
        ginst->is_open = is_open;
        ginst->type_argc = type_argc;
        memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
@@ -2789,8 +2810,10 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
 
        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;
 
@@ -2857,17 +2880,18 @@ mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst
        }
 
        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;
 
@@ -3003,7 +3027,7 @@ select_container (MonoGenericContainer *gc, MonoTypeEnum type)
 
 /* 
  * 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
@@ -3071,6 +3095,7 @@ mono_metadata_get_shared_type (MonoType *type)
  * @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
  * 
@@ -3088,7 +3113,7 @@ mono_metadata_get_shared_type (MonoType *type)
  */
 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);
@@ -3116,9 +3141,17 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
        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;
        }
@@ -3132,7 +3165,7 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
                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;
@@ -3142,7 +3175,7 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
                        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;
@@ -3228,16 +3261,16 @@ hex_dump (const char *buffer, int base, int count)
 #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 */
@@ -3264,11 +3297,11 @@ parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr
                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);
@@ -3301,7 +3334,7 @@ parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr
                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;
        }
 }
 
@@ -3334,8 +3367,8 @@ mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *sum
        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;
@@ -3388,7 +3421,7 @@ mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *sum
  *
  * 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)
@@ -3399,15 +3432,19 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
        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;
@@ -3441,17 +3478,21 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
        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);
@@ -3459,24 +3500,32 @@ 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 = 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;
 }
 
@@ -3510,12 +3559,21 @@ mono_metadata_parse_mh (MonoImage *m, const char *ptr)
  * @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);
+       }
 }
 
 /*
@@ -4493,9 +4551,20 @@ mono_metadata_type_hash (MonoType *t1)
        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:
@@ -5141,7 +5210,6 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
        const char *ptr;
        guint32 len;
        MonoType *type, *type2;
-       MonoType stack_type;
 
        mono_loader_lock ();
 
@@ -5163,15 +5231,8 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
 
        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;
        }
@@ -5183,9 +5244,9 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
                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 ();
 
@@ -5345,7 +5406,17 @@ handle_enum:
                }
                *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;
@@ -5507,7 +5578,7 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
        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;
@@ -5534,6 +5605,7 @@ gboolean
 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;
@@ -5578,6 +5650,12 @@ mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod
        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);
@@ -5644,7 +5722,7 @@ get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGene
        }
        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;
        }
@@ -5704,6 +5782,9 @@ mono_metadata_has_generic_params (MonoImage *image, guint32 token)
        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)
@@ -5729,6 +5810,7 @@ mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 tok
  * 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,
@@ -5937,12 +6019,92 @@ mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
        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)
 {
@@ -5968,30 +6130,63 @@ 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)
 {