Merge pull request #498 from Unroll-Me/master
[mono.git] / mono / metadata / metadata.c
index 4f1cfaf04154bc596df2b0c9703b7516a08239ec..7f5a1757a1b20e18db2f9fe52e09f0936f592e36 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);
@@ -762,7 +757,6 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                        n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
                        n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
                        n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
-                       n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
 
                        /* 3 bits to encode */
                        field_size = rtsize (n, 16 - 3);
@@ -963,6 +957,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 +1240,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 +1271,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 +1286,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 +1366,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);
 
 /*
@@ -1486,6 +1493,8 @@ mono_metadata_cleanup (void)
 {
        g_hash_table_destroy (type_cache);
        type_cache = NULL;
+       g_ptr_array_free (image_sets, TRUE);
+       image_sets = NULL;
 }
 
 /**
@@ -1495,6 +1504,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,
@@ -1507,15 +1517,14 @@ mono_metadata_cleanup (void)
  * (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;
@@ -1557,7 +1566,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");
@@ -1593,14 +1605,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;
@@ -1636,12 +1648,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.
  */
@@ -2158,9 +2177,6 @@ retry:
        }
 }
 
-static MonoImageSet *mscorlib_image_set;
-static GPtrArray *image_sets;
-
 /*
  * get_image_set:
  *
@@ -2257,6 +2273,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.
  */
@@ -2540,7 +2610,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 ();
@@ -2558,9 +2631,9 @@ 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);
        /* delete_image_set () modifies the lists so make a copy */
@@ -2604,74 +2677,23 @@ 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);
+       if (gclass->cached_class && gclass->cached_class->interface_id)
+               mono_unload_interface_id (gclass->cached_class);
 }
 
 static void
@@ -2771,10 +2793,8 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
                        break;
        is_open = (i < type_argc);
 
-       ginst = alloca (size);
-#ifndef MONO_SMALL_CONFIG
-       ginst->id = 0;
-#endif
+       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 *));
@@ -2791,7 +2811,7 @@ 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
@@ -2861,17 +2881,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;
 
@@ -3070,11 +3091,29 @@ mono_metadata_get_shared_type (MonoType *type)
        return NULL;
 }
 
+static gboolean
+compare_type_literals (int class_type, int type_type)
+{
+       /* 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_type)
+               return TRUE;
+       /* NET 1.1 assemblies might encode string and object in a denormalized way.
+        * See #675464.
+        */
+       if (type_type == MONO_TYPE_CLASS && (class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT))
+               return TRUE;
+       return class_type == type_type;
+}
+
 /* 
  * do_mono_metadata_parse_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
  * 
@@ -3092,7 +3131,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);
@@ -3120,9 +3159,13 @@ 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;
+               if (!compare_type_literals (class->byval_arg.type, type->type))
                        return FALSE;
                break;
        }
@@ -3136,7 +3179,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;
@@ -3146,7 +3189,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;
@@ -3392,7 +3435,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)
@@ -3452,7 +3495,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
 
        if (local_var_sig_tok) {
                int idx = (local_var_sig_tok & 0xffffff)-1;
-               if (idx >= t->rows)
+               if (idx >= t->rows || idx < 0)
                        return NULL;
                mono_metadata_decode_row (t, idx, cols, 1);
 
@@ -3474,10 +3517,11 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
                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;
                        }
                }
@@ -3533,12 +3577,17 @@ mono_metadata_parse_mh (MonoImage *m, const char *ptr)
 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);
+       }
 }
 
 /*
@@ -4191,10 +4240,7 @@ mono_backtrace (int limit)
 }
 #endif
 
-#ifndef __GNUC__
-/*#define __alignof__(a) sizeof(a)*/
-#define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
-#endif
+#define abi__alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
 
 /*
  * mono_type_size:
@@ -4211,7 +4257,7 @@ mono_type_size (MonoType *t, int *align)
                return 0;
        }
        if (t->byref) {
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        }
 
@@ -4220,40 +4266,40 @@ mono_type_size (MonoType *t, int *align)
                *align = 1;
                return 0;
        case MONO_TYPE_BOOLEAN:
-               *align = __alignof__(gint8);
+               *align = abi__alignof__(gint8);
                return 1;
        case MONO_TYPE_I1:
        case MONO_TYPE_U1:
-               *align = __alignof__(gint8);
+               *align = abi__alignof__(gint8);
                return 1;
        case MONO_TYPE_CHAR:
        case MONO_TYPE_I2:
        case MONO_TYPE_U2:
-               *align = __alignof__(gint16);
+               *align = abi__alignof__(gint16);
                return 2;               
        case MONO_TYPE_I4:
        case MONO_TYPE_U4:
-               *align = __alignof__(gint32);
+               *align = abi__alignof__(gint32);
                return 4;
        case MONO_TYPE_R4:
-               *align = __alignof__(float);
+               *align = abi__alignof__(float);
                return 4;
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
-               *align = __alignof__(gint64);
+               *align = abi__alignof__(gint64);
                return 8;               
        case MONO_TYPE_R8:
-               *align = __alignof__(double);
+               *align = abi__alignof__(double);
                return 8;               
        case MONO_TYPE_I:
        case MONO_TYPE_U:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_STRING:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_OBJECT:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_VALUETYPE: {
                if (t->data.klass->enumtype)
@@ -4266,7 +4312,7 @@ mono_type_size (MonoType *t, int *align)
        case MONO_TYPE_PTR:
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_ARRAY:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_TYPEDBYREF:
                return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align);
@@ -4282,14 +4328,14 @@ mono_type_size (MonoType *t, int *align)
                        else
                                return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
                } else {
-                       *align = __alignof__(gpointer);
+                       *align = abi__alignof__(gpointer);
                        return sizeof (gpointer);
                }
        }
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                /* FIXME: Martin, this is wrong. */
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        default:
                g_error ("mono_type_size: type 0x%02x unknown", t->type);
@@ -4316,7 +4362,7 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
        int tmp;
 #if SIZEOF_VOID_P == SIZEOF_REGISTER
        int stack_slot_size = sizeof (gpointer);
-       int stack_slot_align = __alignof__ (gpointer);
+       int stack_slot_align = abi__alignof__ (gpointer);
 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
        int stack_slot_size = SIZEOF_REGISTER;
        int stack_slot_align = SIZEOF_REGISTER;
@@ -4361,14 +4407,14 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
                *align = stack_slot_align;
                return stack_slot_size * 3;
        case MONO_TYPE_R4:
-               *align = __alignof__(float);
+               *align = abi__alignof__(float);
                return sizeof (float);          
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
-               *align = __alignof__(gint64);
+               *align = abi__alignof__(gint64);
                return sizeof (gint64);         
        case MONO_TYPE_R8:
-               *align = __alignof__(double);
+               *align = abi__alignof__(double);
                return sizeof (double);
        case MONO_TYPE_VALUETYPE: {
                guint32 size;
@@ -4516,9 +4562,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:
@@ -4536,6 +4593,8 @@ mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, g
                return TRUE;
        if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
                return FALSE;
+       if (p1->serial != p2->serial)
+               return FALSE;
 
        /*
         * We have to compare the image as well because if we didn't,
@@ -4581,6 +4640,9 @@ mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only
        if (signature_only &&
            (c1->byval_arg.type == MONO_TYPE_SZARRAY) && (c2->byval_arg.type == MONO_TYPE_SZARRAY))
                return mono_metadata_class_equal (c1->byval_arg.data.klass, c2->byval_arg.data.klass, signature_only);
+       if (signature_only &&
+           (c1->byval_arg.type == MONO_TYPE_ARRAY) && (c2->byval_arg.type == MONO_TYPE_ARRAY))
+               return do_mono_metadata_type_equal (&c1->byval_arg, &c2->byval_arg, signature_only);
        return FALSE;
 }
 
@@ -5164,7 +5226,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 ();
 
@@ -5186,15 +5247,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;
        }
@@ -5206,9 +5260,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 ();
 
@@ -5368,7 +5422,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;
@@ -5530,7 +5594,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;
@@ -5557,6 +5621,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;
@@ -5601,6 +5666,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);
@@ -5667,7 +5738,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;
        }
@@ -5727,6 +5798,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)
@@ -5752,6 +5826,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,