2009-12-09 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / metadata.c
index 65d23d6194531f7d9cc8e810f5d4ea1fefc8c1f5..50246105d7aab82ea330ae09cb2ab8934aef8de8 100644 (file)
@@ -5,10 +5,14 @@
  *   Miguel de Icaza (miguel@ximian.com)
  *   Paolo Molaro (lupus@ximian.com)
  *
- * (C) 2001-2002 Ximian, Inc.
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  */
 
 #include <config.h>
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "tokentype.h"
 #include "metadata-internals.h"
 #include "class-internals.h"
+#include "verify-internals.h"
 #include "class.h"
+#include "marshal.h"
+#include "gc-internal.h"
+#include <mono/utils/mono-error-internals.h>
+
 
 static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
                                         const char *ptr, const char **rptr);
@@ -33,6 +42,7 @@ static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1,
 static void free_generic_inst (MonoGenericInst *ginst);
 static void free_generic_class (MonoGenericClass *ginst);
 static void free_inflated_method (MonoMethodInflated *method);
+static void mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image);
 
 /*
  * This enumeration is used to describe the data types in the metadata
@@ -175,7 +185,7 @@ const static unsigned char TableSchemas [] = {
 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
        MONO_MT_UINT16,     /* "EventFlags#EventAttribute" }, */
        MONO_MT_STRING_IDX, /* "Name" }, */
-       MONO_MT_TABLE_IDX,  /* "EventType" }, TypeDef or TypeRef  */
+       MONO_MT_TDOR_IDX,  /* "EventType" }, TypeDef or TypeRef or TypeSpec  */
        MONO_MT_END,
 
 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
@@ -445,6 +455,9 @@ typedef struct {
  * mono_meta_table_name:
  * @table: table index
  *
+ * Returns the name of the given ECMA metadata logical format table
+ * as described in ECMA 335, Partition II, Section 22.
+ * 
  * Returns: the name for the @table index
  */
 const char *
@@ -525,7 +538,7 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                        case MONO_TABLE_ASSEMBLYREFOS:
                                g_assert (i == 3);
                                field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
-                       case MONO_TABLE_ASSEMBLYPROCESSOR:
+                       case MONO_TABLE_ASSEMBLYREFPROCESSOR:
                                g_assert (i == 1);
                                field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
                        case MONO_TABLE_CLASSLAYOUT:
@@ -536,13 +549,6 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                                field_size = i ? idx_size (MONO_TABLE_EVENT):
                                        idx_size(MONO_TABLE_TYPEDEF); 
                                break;
-                       case MONO_TABLE_EVENT:
-                               g_assert (i == 2);
-                               n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows, meta->tables [MONO_TABLE_TYPEREF].rows);
-                               n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
-                               /*This is a coded token for 3 tables, so takes 2 bits */
-                               field_size = rtsize (n, 16 - MONO_TYPEDEFORREF_BITS);
-                               break;
                        case MONO_TABLE_EVENT_POINTER:
                                g_assert (i == 0);
                                field_size = idx_size (MONO_TABLE_EVENT); break;
@@ -597,24 +603,18 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                                        idx_size(MONO_TABLE_METHOD);
                                break;
                        case MONO_TABLE_GENERICPARAM:
-                               g_assert (i == 2 || i == 4 || i == 5);
-                               if (i == 2) {
-                                       n = MAX (meta->tables [MONO_TABLE_METHOD].rows, meta->tables [MONO_TABLE_TYPEDEF].rows);
-                                       /*This is a coded token for 2 tables, so takes 1 bit */
-                                       field_size = rtsize (n, 16 - MONO_TYPEORMETHOD_BITS);
-                               } else if (i == 4)
-                                       field_size = idx_size (MONO_TABLE_TYPEDEF);
-                               else if (i == 5)
-                                       field_size = idx_size (MONO_TABLE_TYPEDEF);
+                               g_assert (i == 2);
+                               n = MAX (meta->tables [MONO_TABLE_METHOD].rows, meta->tables [MONO_TABLE_TYPEDEF].rows);
+                               /*This is a coded token for 2 tables, so takes 1 bit */
+                               field_size = rtsize (n, 16 - MONO_TYPEORMETHOD_BITS);
                                break;
-
                        case MONO_TABLE_GENERICPARAMCONSTRAINT:
                                g_assert (i == 0);
                                field_size = idx_size (MONO_TABLE_GENERICPARAM);
                                break;
                                
                        default:
-                               g_assert_not_reached ();
+                               g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex, i);
                        }
                        break;
 
@@ -857,7 +857,7 @@ const char *
 mono_metadata_locate (MonoImage *meta, int table, int idx)
 {
        /* idx == 0 refers always to NULL */
-       g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, "");
+       g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, ""); /*FIXME shouldn't we return NULL here?*/
           
        return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
 }
@@ -914,7 +914,7 @@ mono_metadata_user_string (MonoImage *meta, guint32 index)
 const char *
 mono_metadata_blob_heap (MonoImage *meta, guint32 index)
 {
-       g_return_val_if_fail (index < meta->heap_blob.size, "");
+       g_return_val_if_fail (index < meta->heap_blob.size, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
        return meta->heap_blob.data + index;
 }
 
@@ -1253,16 +1253,17 @@ mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *p
  * Returns: a #MonoArrayType structure describing the array type
  * and dimensions. Memory is allocated from the image mempool.
  *
- * LOCKING: Assumes the loader lock is held.
+ * LOCKING: Acquires the loader lock
  */
 MonoArrayType *
 mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container,
                                const char *ptr, const char **rptr)
 {
        int i;
-       MonoArrayType *array = mono_mempool_alloc0 (m->mempool, sizeof (MonoArrayType));
+       MonoArrayType *array;
        MonoType *etype;
        
+       array = mono_image_alloc0 (m, sizeof (MonoArrayType));
        etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
        if (!etype)
                return NULL;
@@ -1271,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 = g_new0 (int, array->numsizes);
+               array->sizes = 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 = g_new0 (int, array->numlobounds);
+               array->lobounds = 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);
 
@@ -1496,11 +1497,12 @@ mono_metadata_init (void)
 void
 mono_metadata_cleanup (void)
 {
+       /* Has to free this first, as it could reference data in the other caches */
+       if (generic_method_cache)
+               g_hash_table_destroy (generic_method_cache);
        g_hash_table_destroy (type_cache);
        g_hash_table_destroy (generic_inst_cache);
        g_hash_table_destroy (generic_class_cache);
-       if (generic_method_cache)
-               g_hash_table_destroy (generic_method_cache);
        if (generic_signature_cache)
                g_hash_table_destroy (generic_signature_cache);
        type_cache = NULL;
@@ -1547,7 +1549,6 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
        int count = 0;
        gboolean found;
 
-       mono_loader_lock ();
        /*
         * According to the spec, custom modifiers should come before the byref
         * flag, but the IL produced by ilasm from the following signature:
@@ -1580,13 +1581,13 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
        }
 
        if (count) {
-               type = mono_mempool_alloc0 (m->mempool, sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
+               type = mono_image_alloc0 (m, MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod));
                type->num_mods = count;
                if (count > 64)
                        g_warning ("got more than 64 modifiers in type");
        } else {
                type = &stype;
-               memset (type, 0, sizeof (MonoType));
+               memset (type, 0, MONO_SIZEOF_TYPE);
        }
 
        /* Parse pinned, byref and custom modifiers */
@@ -1617,7 +1618,6 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
        type->pinned = pinned ? 1 : 0;
 
        if (!do_mono_metadata_parse_type (type, m, container, ptr, &ptr)) {
-               mono_loader_unlock ();
                return NULL;
        }
 
@@ -1648,13 +1648,11 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
                                    of a MonoClass which currently holds the loader lock.  'type' is local.
                        */
                        if (ret->data.klass == type->data.klass) {
-                               mono_loader_unlock ();
                                return ret;
                        }
                }
                /* No need to use locking since nobody is modifying the hash table */
                if ((cached = g_hash_table_lookup (type_cache, type))) {
-                       mono_loader_unlock ();
                        return cached;
                }
        }
@@ -1662,15 +1660,14 @@ 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_mempool_alloc (m->mempool, sizeof (MonoType));
-               memcpy (type, &stype, sizeof (MonoType));
+               type = mono_image_alloc (m, MONO_SIZEOF_TYPE);
+               memcpy (type, &stype, MONO_SIZEOF_TYPE);
        }
-       mono_loader_unlock ();
        return type;
 }
 
 /*
- * LOCKING: Assumes the loader lock is held.
+ * LOCKING: Acquires the loader lock.
  */
 MonoType*
 mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
@@ -1679,32 +1676,62 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
        return mono_metadata_parse_type_full (m, NULL, mode, opt_attrs, ptr, rptr);
 }
 
+gboolean
+mono_metadata_method_has_param_attrs (MonoImage *m, int def)
+{
+       MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
+       MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
+       guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
+
+       if (def < methodt->rows)
+               lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
+       else
+               lastp = m->tables [MONO_TABLE_PARAM].rows + 1;
+
+       for (i = param_index; i < lastp; ++i) {
+               guint32 flags = mono_metadata_decode_row_col (paramt, i - 1, MONO_PARAM_FLAGS);
+               if (flags)
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
 /*
  * mono_metadata_get_param_attrs:
  *
+ * @m The image to loader parameter attributes from
+ * @def method def token (one based)
+ * @param_count number of params to decode including the return value
+ *
  *   Return the parameter attributes for the method whose MethodDef index is DEF. The 
  * returned memory needs to be freed by the caller. If all the param attributes are
  * 0, then NULL is returned.
  */
 int*
-mono_metadata_get_param_attrs (MonoImage *m, int def)
+mono_metadata_get_param_attrs (MonoImage *m, int def, int param_count)
 {
        MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
        MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
        guint32 cols [MONO_PARAM_SIZE];
-       guint lastp, i, param_index = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def - 1, MONO_METHOD_PARAMLIST);
+       guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
        int *pattrs = NULL;
 
        if (def < methodt->rows)
-               lastp = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def, MONO_METHOD_PARAMLIST);
+               lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
        else
                lastp = paramt->rows + 1;
 
        for (i = param_index; i < lastp; ++i) {
-               mono_metadata_decode_row (&m->tables [MONO_TABLE_PARAM], i - 1, cols, MONO_PARAM_SIZE);
+               mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
                if (cols [MONO_PARAM_FLAGS]) {
                        if (!pattrs)
-                               pattrs = g_new0 (int, 1 + (lastp - param_index));
+                               pattrs = g_new0 (int, param_count);
+                       /* at runtime we just ignore this kind of malformed file:
+                       * the verifier can signal the error to the user
+                       */
+                       if (cols [MONO_PARAM_SEQUENCE] >= param_count)
+                               continue;
                        pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
                }
        }
@@ -1778,33 +1805,42 @@ mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
 {
        MonoMethodSignature *sig;
 
-       mono_loader_lock ();
-       sig = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+       sig = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_SIGNATURE + ((gint32)nparams) * sizeof (MonoType*));
        sig->param_count = nparams;
        sig->sentinelpos = -1;
-       mono_loader_unlock ();
 
        return sig;
 }
 
-MonoMethodSignature*
-mono_metadata_signature_dup_full (MonoMemPool *mp, MonoMethodSignature *sig)
+static MonoMethodSignature*
+mono_metadata_signature_dup_internal (MonoImage *image, MonoMemPool *mp, MonoMethodSignature *sig)
 {
        int sigsize;
+       MonoMethodSignature *ret;
+       sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
 
-       sigsize = sizeof (MonoMethodSignature) + (sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *);
-
-       if (mp) {
-               MonoMethodSignature *ret;
-               mono_loader_lock ();
+       if (image) {
+               ret = mono_image_alloc (image, sigsize);
+       } else if (mp) {
                ret = mono_mempool_alloc (mp, sigsize);
-               mono_loader_unlock ();
-
-               memcpy (ret, sig, sigsize);
-               return ret;
        } else {
-               return g_memdup (sig, sigsize);
+               ret = g_malloc (sigsize);
        }
+       memcpy (ret, sig, sigsize);
+       return ret;
+}
+
+MonoMethodSignature*
+mono_metadata_signature_dup_full (MonoImage *image, MonoMethodSignature *sig)
+{
+       return mono_metadata_signature_dup_internal (image, NULL, sig);
+}
+
+/*The mempool is accessed without synchronization*/
+MonoMethodSignature*
+mono_metadata_signature_dup_mempool (MonoMemPool *mp, MonoMethodSignature *sig)
+{
+       return mono_metadata_signature_dup_internal (NULL, mp, sig);
 }
 
 /*
@@ -1822,6 +1858,17 @@ mono_metadata_signature_dup (MonoMethodSignature *sig)
        return mono_metadata_signature_dup_full (NULL, sig);
 }
 
+/*
+ * mono_metadata_signature_size:
+ *
+ *   Return the amount of memory allocated to SIG.
+ */
+guint32
+mono_metadata_signature_size (MonoMethodSignature *sig)
+{
+       return MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
+}
+
 /*
  * mono_metadata_parse_method_signature:
  * @m: metadata context
@@ -1860,7 +1907,8 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c
        param_count = mono_metadata_decode_value (ptr, &ptr);
 
        if (def)
-               pattrs = mono_metadata_get_param_attrs (m, def);
+               pattrs = mono_metadata_get_param_attrs (m, def, param_count + 1); /*Must be + 1 since signature's param count doesn't account for the return value */
+
        method = mono_metadata_signature_alloc (m, param_count);
        method->hasthis = hasthis;
        method->explicit_this = explicit_this;
@@ -1879,10 +1927,16 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c
 
        for (i = 0; i < method->param_count; ++i) {
                if (*ptr == MONO_TYPE_SENTINEL) {
-                       if (method->call_convention != MONO_CALL_VARARG || def)
-                               g_error ("found sentinel for methoddef or no vararg method");
-                       if (method->sentinelpos >= 0)
-                               g_error ("found sentinel twice in the same signature");
+                       if (method->call_convention != MONO_CALL_VARARG || def) {
+                               g_warning ("found sentinel for methoddef or no vararg method 0x%08x on image %s", def, m->name);
+                               g_free (pattrs);
+                               return NULL;
+                       }
+                       if (method->sentinelpos >= 0) {
+                               g_warning ("found sentinel twice in the same signature for method 0x%08x on image %s", def, m->name);
+                               g_free (pattrs);
+                               return NULL;
+                       }
                        method->sentinelpos = i;
                        ptr++;
                }
@@ -1981,7 +2035,7 @@ inflated_method_equal (gconstpointer a, gconstpointer b)
        const MonoMethodInflated *mb = b;
        if (ma->declaring != mb->declaring)
                return FALSE;
-       if (ma->is_mb_open != mb->is_mb_open)
+       if (ma->method.method.is_mb_open != mb->method.method.is_mb_open)
                return FALSE;
        return mono_metadata_generic_context_equal (&ma->context, &mb->context);
 }
@@ -1990,7 +2044,7 @@ static guint
 inflated_method_hash (gconstpointer a)
 {
        const MonoMethodInflated *ma = a;
-       return (mono_metadata_generic_context_hash (&ma->context) ^ mono_aligned_addr_hash (ma->declaring)) + ma->is_mb_open;
+       return (mono_metadata_generic_context_hash (&ma->context) ^ mono_aligned_addr_hash (ma->declaring)) + ma->method.method.is_mb_open;
 }
 
 static gboolean
@@ -2085,23 +2139,43 @@ retry:
                goto retry;
        case MONO_TYPE_FNPTR:
                return signature_in_image (type->data.method, image);
-       case MONO_TYPE_VAR:
-               if (type->data.generic_param->owner) {
-                       g_assert (!type->data.generic_param->owner->is_method);
-                       return type->data.generic_param->owner->owner.klass->image == image;
+       case MONO_TYPE_VAR: {
+               MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
+               if (container) {
+                       g_assert (!container->is_method);
+                       /*
+                        * FIXME: The following check is here solely
+                        * for monodis, which uses the internal
+                        * function
+                        * mono_metadata_load_generic_params().  The
+                        * caller of that function needs to fill in
+                        * owner->klass or owner->method of the
+                        * returned struct, but monodis doesn't do
+                        * that.  The image unloading depends on that,
+                        * however, so a crash results without this
+                        * check.
+                        */
+                       if (!container->owner.klass)
+                               return container->image == image;
+                       return container->owner.klass->image == image;
                } else {
                        return type->data.generic_param->image == image;
                }
-       case MONO_TYPE_MVAR:
-               if (type->data.generic_param->owner) {
-                       g_assert (type->data.generic_param->owner->is_method);
-                       if (!type->data.generic_param->owner->owner.method)
+       }
+       case MONO_TYPE_MVAR: {
+               MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
+               if (type->data.generic_param->image == image)
+                       return TRUE;
+               if (container) {
+                       g_assert (container->is_method);
+                       if (!container->owner.method)
                                /* RefEmit created generic param whose method is not finished */
-                               return FALSE;
-                       return type->data.generic_param->owner->owner.method->klass->image == image;
+                               return container->image == image;
+                       return container->owner.method->klass->image == image;
                } else {
                        return type->data.generic_param->image == image;
                }
+       }
        default:
                /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
                return image == mono_class_from_mono_type (type)->image;
@@ -2145,9 +2219,11 @@ inflated_method_in_image (gpointer key, gpointer value, gpointer data)
        MonoImage *image = data;
        MonoMethodInflated *method = key;
 
+       // FIXME:
+       // https://bugzilla.novell.com/show_bug.cgi?id=458168
        return method->declaring->klass->image == image ||
                (method->context.class_inst && ginst_in_image (method->context.class_inst, image)) ||
-               (method->context.method_inst && ginst_in_image (method->context.method_inst, image));
+               (method->context.method_inst && ginst_in_image (method->context.method_inst, image)) || (((MonoMethod*)method)->signature && signature_in_image (mono_method_signature ((MonoMethod*)method), image));
 }
 
 static gboolean
@@ -2156,7 +2232,7 @@ inflated_signature_in_image (gpointer key, gpointer value, gpointer data)
        MonoImage *image = data;
        MonoInflatedMethodSignature *sig = key;
 
-       return /* signature_in_image (sig->sig, image) || */
+       return signature_in_image (sig->sig, image) ||
                (sig->context.class_inst && ginst_in_image (sig->context.class_inst, image)) ||
                (sig->context.method_inst && ginst_in_image (sig->context.method_inst, image));
 }      
@@ -2196,6 +2272,8 @@ free_inflated_method (MonoMethodInflated *imethod)
        int i;
        MonoMethod *method = (MonoMethod*)imethod;
 
+       mono_marshal_free_inflated_wrappers (method);
+
        if (method->signature)
                mono_metadata_free_inflated_signature (method->signature);
 
@@ -2222,7 +2300,6 @@ free_generic_inst (MonoGenericInst *ginst)
 
        for (i = 0; i < ginst->type_argc; ++i)
                mono_metadata_free_type (ginst->type_argv [i]);
-       g_free (ginst->type_argv);
        g_free (ginst);
 }
 
@@ -2238,13 +2315,8 @@ free_generic_class (MonoGenericClass *gclass)
 
                /* Allocated in mono_class_init () */
                g_free (class->methods);
-               g_free (class->properties);
-               /* Allocated in mono_class_setup_fields () */
-               if (class->fields) {
-                       for (i = 0; i < class->field.count; ++i) {
-                               g_free (class->fields [i].generic_info);
-                       }
-               }
+               if (class->ext)
+                       g_free (class->ext->properties);
                /* Allocated in mono_generic_class_get_class () */
                g_free (class->interfaces);
                g_free (class);
@@ -2254,10 +2326,10 @@ free_generic_class (MonoGenericClass *gclass)
                for (i = 0; i < dgclass->count_fields; ++i) {
                        MonoClassField *field = dgclass->fields + i;
                        mono_metadata_free_type (field->type);
-                       if (field->generic_info) {
-                               g_free (field->generic_info);
-                       }
                        g_free ((char*)field->name);
+#if HAVE_SGEN_GC
+                       MONO_GC_UNREGISTER_ROOT (dgclass->field_objects [i]);
+#endif
                }
                for (i = 0; i < dgclass->count_properties; ++i) {
                        MonoProperty *property = dgclass->properties + i;
@@ -2273,6 +2345,8 @@ free_generic_class (MonoGenericClass *gclass)
                g_free (dgclass->fields);
                g_free (dgclass->properties);
                g_free (dgclass->events);
+               g_free (dgclass->field_objects);
+               g_free (dgclass->field_generic_types);
                if (!mono_generic_class_is_generic_type_definition (gclass))
                        g_free (gclass->cached_class);
        }
@@ -2348,40 +2422,37 @@ MonoGenericInst *
 mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
 {
        MonoGenericInst *ginst;
-       MonoGenericInst helper;
+       gboolean is_open;
        int i;
-
-       helper.type_argc = type_argc;
-       helper.type_argv = type_argv;
-       helper.id = 0;
+       int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
 
        for (i = 0; i < type_argc; ++i)
                if (mono_class_is_open_constructed_type (type_argv [i]))
                        break;
-       helper.is_open = (i < type_argc);
+       is_open = (i < type_argc);
+
+       ginst = alloca (size);
+       ginst->id = 0;
+       ginst->is_open = is_open;
+       ginst->type_argc = type_argc;
+       memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
 
-       /*dump_ginst (&helper);*/
        mono_loader_lock ();
-       ginst = g_hash_table_lookup (generic_inst_cache, &helper);
-       if (ginst) {
-               mono_loader_unlock ();
-               /*g_print (" found cached\n");*/
-               return ginst;
-       }
 
-       ginst = g_new0 (MonoGenericInst, 1);
-       ginst->type_argc = type_argc;
-       ginst->type_argv = g_new (MonoType*, type_argc);
-       ginst->id = ++next_generic_inst_id;
-       ginst->is_open = helper.is_open;
+       ginst = g_hash_table_lookup (generic_inst_cache, ginst);
+       if (!ginst) {
+               ginst = g_malloc (size);
+               ginst->id = ++next_generic_inst_id;
+               ginst->is_open = is_open;
+               ginst->type_argc = type_argc;
 
-       for (i = 0; i < type_argc; ++i)
-               ginst->type_argv [i] = mono_metadata_type_dup (NULL, type_argv [i]);
+               for (i = 0; i < type_argc; ++i)
+                       ginst->type_argv [i] = mono_metadata_type_dup (NULL, type_argv [i]);
 
-       g_hash_table_insert (generic_inst_cache, ginst, ginst);
+               g_hash_table_insert (generic_inst_cache, ginst, ginst);
+       }
 
        mono_loader_unlock ();
-       /*g_print (" inserted\n");*/
        return ginst;
 }
 
@@ -2453,26 +2524,34 @@ mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst
  * mono_metadata_inflate_generic_inst:
  *
  * Instantiate the generic instance @ginst with the context @context.
+ * Check @error for success.
  *
  */
 MonoGenericInst *
-mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context)
+mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context, MonoError *error)
 {
        MonoType **type_argv;
-       MonoGenericInst *nginst;
-       int i;
+       MonoGenericInst *nginst = NULL;
+       int i, count = 0;
+
+       mono_error_init (error);
 
        if (!ginst->is_open)
                return ginst;
 
        type_argv = g_new0 (MonoType*, ginst->type_argc);
 
-       for (i = 0; i < ginst->type_argc; i++)
-               type_argv [i] = mono_class_inflate_generic_type (ginst->type_argv [i], context);
+       for (i = 0; i < ginst->type_argc; i++) {
+               type_argv [i] = mono_class_inflate_generic_type_checked (ginst->type_argv [i], context, error);
+               if (!mono_error_ok (error))
+                       goto cleanup;
+               ++count;
+       }
 
        nginst = mono_metadata_get_generic_inst (ginst->type_argc, type_argv);
 
-       for (i = 0; i < ginst->type_argc; i++)
+cleanup:
+       for (i = 0; i < count; i++)
                mono_metadata_free_type (type_argv [i]);
        g_free (type_argv);
 
@@ -2569,7 +2648,7 @@ select_container (MonoGenericContainer *gc, MonoTypeEnum type)
  * @generic_container: Our MonoClass's or MonoMethodNormal's MonoGenericContainer;
  *                     see mono_metadata_parse_type_full() for details.
  * Internal routine to parse a generic type parameter.
- * LOCKING: Assumes the loader lock is held.
+ * LOCKING: Acquires the loader lock
  */
 static MonoGenericParam *
 mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
@@ -2582,17 +2661,51 @@ mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_c
        generic_container = select_container (generic_container, type);
        if (!generic_container) {
                /* Create dummy MonoGenericParam */
-               MonoGenericParam *param = mono_mempool_alloc0 (m->mempool, sizeof (MonoGenericParam));
-               param->name = mono_mempool_alloc0 (m->mempool, 8);
-               sprintf ((char*)param->name, "%d", index);
+               MonoGenericParam *param;
+
+               param = mono_image_alloc0 (m, sizeof (MonoGenericParam));
                param->num = index;
                param->image = m;
 
                return param;
        }
 
-       g_assert (index < generic_container->type_argc);
-       return &generic_container->type_params [index];
+       if (index >= generic_container->type_argc)
+               return NULL;
+
+       return mono_generic_container_get_param (generic_container, index);
+}
+
+/*
+ * mono_metadata_get_shared_type:
+ *
+ *   Return a shared instance of TYPE, if available, NULL otherwise.
+ * Shared MonoType instances help save memory. Their contents should not be modified
+ * by the caller. They do not need to be freed as their lifetime is bound by either
+ * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
+ * instance they are embedded in. If they are freed, they should be freed using
+ * mono_metadata_free_type () instead of g_free ().
+ */
+MonoType*
+mono_metadata_get_shared_type (MonoType *type)
+{
+       MonoType *cached;
+
+       /* No need to use locking since nobody is modifying the hash table */
+       if ((cached = g_hash_table_lookup (type_cache, type)))
+               return cached;
+
+       switch (type->type){
+       case MONO_TYPE_CLASS:
+       case MONO_TYPE_VALUETYPE:
+               if (type == &type->data.klass->byval_arg)
+                       return type;
+               if (type == &type->data.klass->this_arg)
+                       return type;
+               break;
+       }
+
+       return NULL;
 }
 
 /* 
@@ -2656,6 +2769,8 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
                if (!etype)
                        return FALSE;
                type->data.klass = mono_class_from_mono_type (etype);
+               if (!type->data.klass)
+                       return FALSE;
                break;
        }
        case MONO_TYPE_PTR:
@@ -2665,19 +2780,28 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
                break;
        case MONO_TYPE_FNPTR:
                type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr);
+               if (!type->data.method)
+                       return FALSE;
                break;
        case MONO_TYPE_ARRAY:
                type->data.array = mono_metadata_parse_array_full (m, container, ptr, &ptr);
+               if (!type->data.array)
+                       return FALSE;
                break;
        case MONO_TYPE_MVAR:
+               if (container && !container->is_method)
+                       return FALSE;
        case MONO_TYPE_VAR:
                type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr);
+               if (!type->data.generic_param)
+                       return FALSE;
                break;
        case MONO_TYPE_GENERICINST:
                ok = do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr);
                break;
        default:
-               g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type->type);
+               g_warning ("type 0x%02x not handled in do_mono_metadata_parse_type on image %s", type->type, m->name);
+               return FALSE;
        }
        
        if (rptr)
@@ -2784,7 +2908,7 @@ parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr
                        int i;
                        mh->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_mempool_alloc0 (m->mempool, sizeof (MonoExceptionClause) * mh->num_clauses);
+                       mh->clauses = mono_image_alloc0 (m, sizeof (MonoExceptionClause) * mh->num_clauses);
                        for (i = 0; i < mh->num_clauses; ++i) {
                                MonoExceptionClause *ec = &mh->clauses [i];
                                guint32 tof_value;
@@ -2833,7 +2957,7 @@ parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr
  * info about local variables and optional exception tables.
  * This is a Mono runtime internal function.
  *
- * LOCKING: Assumes the loader lock is held.
+ * LOCKING: Acquires the loader lock.
  *
  * Returns: a MonoMethodHeader allocated from the image mempool.
  */
@@ -2850,30 +2974,14 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
        
        g_return_val_if_fail (ptr != NULL, NULL);
 
-       mono_loader_lock ();
        switch (format) {
        case METHOD_HEADER_TINY_FORMAT:
-               mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
+               mh = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER);
                ptr++;
                mh->max_stack = 8;
                local_var_sig_tok = 0;
                mh->code_size = flags >> 2;
                mh->code = (unsigned char*)ptr;
-               mono_loader_unlock ();
-               return mh;
-       case METHOD_HEADER_TINY_FORMAT1:
-               mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
-               ptr++;
-               mh->max_stack = 8;
-               local_var_sig_tok = 0;
-
-               /*
-                * The spec claims 3 bits, but the Beta2 is
-                * incorrect
-                */
-               mh->code_size = flags >> 2;
-               mh->code = (unsigned char*)ptr;
-               mono_loader_unlock ();
                return mh;
        case METHOD_HEADER_FAT_FORMAT:
                fat_flags = read16 (ptr);
@@ -2902,7 +3010,6 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
                ptr = (char*)code + code_size;
                break;
        default:
-               mono_loader_unlock ();
                return NULL;
        }
                       
@@ -2913,24 +3020,27 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
                int len=0, i, bsize;
 
                mono_metadata_decode_row (t, (local_var_sig_tok & 0xffffff)-1, cols, 1);
+
+               if (!mono_verifier_verify_standalone_signature (m, cols [MONO_STAND_ALONE_SIGNATURE], NULL))
+                       return NULL;
+
                locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
                bsize = mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
                if (*locals_ptr != 0x07)
                        g_warning ("wrong signature for locals blob");
                locals_ptr++;
                len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
-               mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+               mh = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*));
                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);
                        if (!mh->locals [i]) {
-                               mono_loader_unlock ();
                                return NULL;
                        }
                }
        } else {
-               mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
+               mh = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER);
        }
        mh->code = code;
        mh->code_size = code_size;
@@ -2938,7 +3048,6 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
        mh->init_locals = init_locals;
        if (fat_flags & METHOD_HEADER_MORE_SECTS)
                parse_section_data (m, mh, (const unsigned char*)ptr);
-       mono_loader_unlock ();
        return mh;
 }
 
@@ -3302,7 +3411,7 @@ mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
                loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
 
        if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
-               g_assert_not_reached ();
+               return 0;
 
        /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
        return loc.result + 1;
@@ -3333,7 +3442,7 @@ mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
                loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx);
 
        if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
-               g_assert_not_reached ();
+               return 0;
 
        /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
        return loc.result + 1;
@@ -3343,16 +3452,20 @@ mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
  * mono_metadata_interfaces_from_typedef_full:
  * @meta: metadata context
  * @index: typedef token
+ * @interfaces: Out parameter used to store the interface array
+ * @count: Out parameter used to store the number of interfaces
+ * @heap_alloc_result: if TRUE the result array will be g_malloc'd
+ * @context: The generic context
  * 
  * The array of interfaces that the @index typedef token implements is returned in
- * @interfaces. The number of elemnts in the array is returned in @count.
+ * @interfaces. The number of elements in the array is returned in @count. 
  *
  * LOCKING: Assumes the loader lock is held.
  *
  * Returns: TRUE on success, FALSE on failure.
  */
 gboolean
-mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, MonoGenericContext *context)
+mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context)
 {
        MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
        locator_t loc;
@@ -3391,9 +3504,10 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono
                ++pos;
        }
 
-       mono_loader_lock ();
-       result = mono_mempool_alloc0 (meta->mempool, sizeof (MonoClass*) * (pos - start));
-       mono_loader_unlock ();
+       if (heap_alloc_result)
+               result = g_new0 (MonoClass*, pos - start);
+       else
+               result = mono_image_alloc0 (meta, sizeof (MonoClass*) * (pos - start));
 
        pos = start;
        while (pos < tdef->rows) {
@@ -3414,6 +3528,20 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono
        return TRUE;
 }
 
+/*
+ * @meta: metadata context
+ * @index: typedef token
+ * @count: Out parameter used to store the number of interfaces
+ * 
+ * The array of interfaces that the @index typedef token implements is returned in
+ * @interfaces. The number of elements in the array is returned in @count. The returned
+ * array is g_malloc'd and the caller must free it.
+ *
+ * LOCKING: Acquires the loader lock .
+ *
+ * Returns: the interface array on success, NULL on failure.
+ */
+
 MonoClass**
 mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
 {
@@ -3421,7 +3549,7 @@ mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *co
        gboolean rv;
 
        mono_loader_lock ();
-       rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, NULL);
+       rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, TRUE, NULL);
        mono_loader_unlock ();
        if (rv)
                return interfaces;
@@ -3677,7 +3805,7 @@ mono_type_size (MonoType *t, int *align)
                return sizeof (gpointer);
        case MONO_TYPE_VALUETYPE: {
                if (t->data.klass->enumtype)
-                       return mono_type_size (t->data.klass->enum_basetype, align);
+                       return mono_type_size (mono_class_enum_basetype (t->data.klass), align);
                else
                        return mono_class_value_size (t->data.klass, (guint32*)align);
        }
@@ -3698,7 +3826,7 @@ mono_type_size (MonoType *t, int *align)
 
                if (container_class->valuetype) {
                        if (container_class->enumtype)
-                               return mono_type_size (container_class->enum_basetype, align);
+                               return mono_type_size (mono_class_enum_basetype (container_class), align);
                        else
                                return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
                } else {
@@ -3734,6 +3862,13 @@ int
 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);
+#elif SIZEOF_VOID_P < SIZEOF_REGISTER
+       int stack_slot_size = SIZEOF_REGISTER;
+       int stack_slot_align = SIZEOF_REGISTER;
+#endif
 
        g_assert (t != NULL);
 
@@ -3741,8 +3876,8 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
                align = &tmp;
 
        if (t->byref) {
-               *align = __alignof__(gpointer);
-               return sizeof (gpointer);
+               *align = stack_slot_align;
+               return stack_slot_size;
        }
 
        switch (t->type){
@@ -3763,16 +3898,16 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
        case MONO_TYPE_PTR:
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_ARRAY:
-               *align = __alignof__(gpointer);
-               return sizeof (gpointer);
+               *align = stack_slot_align;
+               return stack_slot_size;
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                g_assert (allow_open);
-               *align = __alignof__(gpointer);
-               return sizeof (gpointer);
+               *align = stack_slot_align;
+               return stack_slot_size;
        case MONO_TYPE_TYPEDBYREF:
-               *align = __alignof__(gpointer);
-               return sizeof (gpointer) * 3;
+               *align = stack_slot_align;
+               return stack_slot_size * 3;
        case MONO_TYPE_R4:
                *align = __alignof__(float);
                return sizeof (float);          
@@ -3787,15 +3922,15 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
                guint32 size;
 
                if (t->data.klass->enumtype)
-                       return mono_type_stack_size_internal (t->data.klass->enum_basetype, align, allow_open);
+                       return mono_type_stack_size_internal (mono_class_enum_basetype (t->data.klass), align, allow_open);
                else {
                        size = mono_class_value_size (t->data.klass, (guint32*)align);
 
-                       *align = *align + __alignof__(gpointer) - 1;
-                       *align &= ~(__alignof__(gpointer) - 1);
+                       *align = *align + stack_slot_align - 1;
+                       *align &= ~(stack_slot_align - 1);
 
-                       size += sizeof (gpointer) - 1;
-                       size &= ~(sizeof (gpointer) - 1);
+                       size += stack_slot_size - 1;
+                       size &= ~(stack_slot_size - 1);
 
                        return size;
                }
@@ -3809,21 +3944,21 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
 
                if (container_class->valuetype) {
                        if (container_class->enumtype)
-                               return mono_type_stack_size_internal (container_class->enum_basetype, align, allow_open);
+                               return mono_type_stack_size_internal (mono_class_enum_basetype (container_class), align, allow_open);
                        else {
                                guint32 size = mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
 
-                               *align = *align + __alignof__(gpointer) - 1;
-                               *align &= ~(__alignof__(gpointer) - 1);
+                               *align = *align + stack_slot_align - 1;
+                               *align &= ~(stack_slot_align - 1);
 
-                               size += sizeof (gpointer) - 1;
-                               size &= ~(sizeof (gpointer) - 1);
+                               size += stack_slot_size - 1;
+                               size &= ~(stack_slot_size - 1);
 
                                return size;
                        }
                } else {
-                       *align = __alignof__(gpointer);
-                       return sizeof (gpointer);
+                       *align = stack_slot_align;
+                       return stack_slot_size;
                }
        }
        default:
@@ -3879,9 +4014,9 @@ mono_metadata_generic_context_hash (const MonoGenericContext *context)
        /* FIXME: check if this seed is good enough */
        guint hash = 0xc01dfee7;
        if (context->class_inst)
-               hash = ((hash << 5) - hash) ^ context->class_inst->id;
+               hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->class_inst);
        if (context->method_inst)
-               hash = ((hash << 5) - hash) ^ context->method_inst->id;
+               hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->method_inst);
        return hash;
 }
 
@@ -3924,10 +4059,23 @@ mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, g
 {
        if (p1 == p2)
                return TRUE;
-       if (p1->num != p2->num)
+       if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
                return FALSE;
 
-       if (p1->owner == p2->owner)
+       /*
+        * We have to compare the image as well because if we didn't,
+        * the generic_inst_cache lookup wouldn't care about the image
+        * of generic params, so what could happen is that a generic
+        * inst with params from image A is put into the cache, then
+        * image B gets that generic inst from the cache, image A is
+        * unloaded, so the inst is deleted, but image B still retains
+        * a pointer to it.
+        *
+        * The AOT runtime doesn't set the image when it's decoding
+        * types, so we only compare it when the owner is NULL.
+        */
+       if (mono_generic_param_owner (p1) == mono_generic_param_owner (p2) &&
+           (mono_generic_param_owner (p1) || p1->image == p2->image))
                return TRUE;
 
        /*
@@ -4125,32 +4273,30 @@ mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *s
 
 /**
  * mono_metadata_type_dup:
- * @mp: mempool to use
+ * @image: image to alloc memory from
  * @original: type to duplicate
  *
- * Returns: copy of type allocated from mempool (or from the heap, if @mp is null).
+ * Returns: copy of type allocated from the image's mempool (or from the heap, if @image is null).
  */
 MonoType *
-mono_metadata_type_dup (MonoMemPool *mp, const MonoType *o)
+mono_metadata_type_dup (MonoImage *image, const MonoType *o)
 {
        MonoType *r = NULL;
-       int sizeof_o = sizeof (MonoType);
+       int sizeof_o = MONO_SIZEOF_TYPE;
        if (o->num_mods)
-               sizeof_o += (o->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
+               sizeof_o += o->num_mods  * sizeof (MonoCustomMod);
 
-       mono_loader_lock ();
-       r = mp ? mono_mempool_alloc0 (mp, sizeof_o) : g_malloc (sizeof_o);
-       mono_loader_unlock ();
+       r = image ? mono_image_alloc0 (image, sizeof_o) : g_malloc (sizeof_o);
 
        memcpy (r, o, sizeof_o);
 
        if (o->type == MONO_TYPE_PTR) {
-               r->data.type = mono_metadata_type_dup (mp, o->data.type);
+               r->data.type = mono_metadata_type_dup (image, o->data.type);
        } else if (o->type == MONO_TYPE_ARRAY) {
-               r->data.array = mono_dup_array_type (mp, o->data.array);
+               r->data.array = mono_dup_array_type (image, o->data.array);
        } else if (o->type == MONO_TYPE_FNPTR) {
                /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
-               r->data.method = mono_metadata_signature_deep_dup (mp, o->data.method);
+               r->data.method = mono_metadata_signature_deep_dup (image, o->data.method);
        }
        return r;
 }
@@ -4218,12 +4364,19 @@ void
 mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
                          MonoMarshalSpec **marshal_spec)
 {
-       return mono_metadata_field_info_with_mempool (NULL, meta, index, offset, rva, marshal_spec);
+       mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, FALSE);
 }
 
 void
-mono_metadata_field_info_with_mempool (MonoMemPool *mempool, MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
+mono_metadata_field_info_with_mempool (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
                          MonoMarshalSpec **marshal_spec)
+{
+       mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, TRUE);
+}
+
+static void
+mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
+                                      MonoMarshalSpec **marshal_spec, gboolean alloc_from_image)
 {
        MonoTableInfo *tdef;
        locator_t loc;
@@ -4263,7 +4416,7 @@ mono_metadata_field_info_with_mempool (MonoMemPool *mempool, MonoImage *meta, gu
                const char *p;
                
                if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
-                       *marshal_spec = mono_metadata_parse_marshal_spec_with_mempool (mempool, p);
+                       *marshal_spec = mono_metadata_parse_marshal_spec_full (alloc_from_image ? meta : NULL, p);
                }
        }
 
@@ -4536,6 +4689,7 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
        const char *ptr;
        guint32 len;
        MonoType *type, *type2;
+       MonoType stack_type;
 
        mono_loader_lock ();
 
@@ -4549,9 +4703,16 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
 
        mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
        ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
+
+       if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], NULL)) {
+               mono_loader_unlock ();
+               return NULL;
+       }
+
        len = mono_metadata_decode_value (ptr, &ptr);
 
-       type = mono_mempool_alloc0 (image->mempool, sizeof (MonoType));
+       type = &stack_type;
+       memset (type, 0, MONO_SIZEOF_TYPE);
 
        if (*ptr == MONO_TYPE_BYREF) {
                type->byref = 1;
@@ -4570,21 +4731,23 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
                return type2;
        }
 
-       g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type);
+       type2 = mono_image_alloc (image, MONO_SIZEOF_TYPE);
+       memcpy (type2, type, MONO_SIZEOF_TYPE);
+       g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
 
        mono_loader_unlock ();
 
-       return type;
+       return type2;
 }
 
 
 static char*
-mono_mempool_strndup (MonoMemPool *mp, const char *data, guint len)
+mono_image_strndup (MonoImage *image, const char *data, guint len)
 {
        char *res;
-       if (!mp)
+       if (!image)
                return g_strndup (data, len);
-       res = mono_mempool_alloc (mp, len + 1);
+       res = mono_image_alloc (image, len + 1);
        memcpy (res, data, len);
        res [len] = 0;
        return res;
@@ -4593,11 +4756,11 @@ mono_mempool_strndup (MonoMemPool *mp, const char *data, guint len)
 MonoMarshalSpec *
 mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
 {
-       return mono_metadata_parse_marshal_spec_with_mempool (NULL, ptr);
+       return mono_metadata_parse_marshal_spec_full (NULL, ptr);
 }
 
 MonoMarshalSpec *
-mono_metadata_parse_marshal_spec_with_mempool (MonoMemPool *mempool, const char *ptr)
+mono_metadata_parse_marshal_spec_full (MonoImage *image, const char *ptr)
 {
        MonoMarshalSpec *res;
        int len;
@@ -4605,8 +4768,8 @@ mono_metadata_parse_marshal_spec_with_mempool (MonoMemPool *mempool, const char
 
        /* fixme: this is incomplete, but I cant find more infos in the specs */
 
-       if (mempool)
-               res = mono_mempool_alloc0 (mempool, sizeof (MonoMarshalSpec));
+       if (image)
+               res = mono_image_alloc0 (image, sizeof (MonoMarshalSpec));
        else
                res = g_new0 (MonoMarshalSpec, 1);
        
@@ -4657,11 +4820,11 @@ mono_metadata_parse_marshal_spec_with_mempool (MonoMemPool *mempool, const char
                ptr += len;
                /* read custom marshaler type name */
                len = mono_metadata_decode_value (ptr, &ptr);
-               res->data.custom_data.custom_name = mono_mempool_strndup (mempool, ptr, len);           
+               res->data.custom_data.custom_name = mono_image_strndup (image, ptr, len);               
                ptr += len;
                /* read cookie string */
                len = mono_metadata_decode_value (ptr, &ptr);
-               res->data.custom_data.cookie = mono_mempool_strndup (mempool, ptr, len);
+               res->data.custom_data.cookie = mono_image_strndup (image, ptr, len);
        }
 
        if (res->native == MONO_NATIVE_SAFEARRAY) {
@@ -4783,7 +4946,7 @@ handle_enum:
        case MONO_TYPE_PTR: return MONO_NATIVE_UINT;
        case MONO_TYPE_VALUETYPE: /*FIXME*/
                if (type->data.klass->enumtype) {
-                       t = type->data.klass->enum_basetype->type;
+                       t = mono_class_enum_basetype (type->data.klass)->type;
                        goto handle_enum;
                }
                if (type->data.klass == mono_defaults.handleref_class){
@@ -5005,7 +5168,7 @@ get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGene
        guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
        guint32 i, token, found;
        MonoClass *klass, **res;
-       GList *cons = NULL, *tmp;
+       GSList *cons = NULL, *tmp;
        MonoGenericContext *context = &container->context;
 
        *constraints = NULL;
@@ -5015,7 +5178,11 @@ get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGene
                if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
                        token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
                        klass = mono_class_get_full (image, token, context);
-                       cons = g_list_append (cons, klass);
+                       if (!klass) {
+                               g_slist_free (cons);
+                               return FALSE;
+                       }
+                       cons = g_slist_append (cons, klass);
                        ++found;
                } else {
                        /* contiguous list finished */
@@ -5029,7 +5196,7 @@ get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGene
        for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
                res [i] = tmp->data;
        }
-       g_list_free (cons);
+       g_slist_free (cons);
        *constraints = res;
        return TRUE;
 }
@@ -5085,9 +5252,28 @@ mono_metadata_has_generic_params (MonoImage *image, guint32 token)
        return mono_metadata_get_generic_param_row (image, token, &owner);
 }
 
+gboolean
+mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 token,
+                                             MonoGenericContainer *container)
+{
+
+       guint32 start_row, i, owner;
+       if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
+               return TRUE;
+       for (i = 0; i < container->type_argc; i++) {
+               if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container))
+                       return FALSE;
+       }
+       return TRUE;
+}
+
 /*
  * mono_metadata_load_generic_param_constraints:
  *
+ * @image: metadata context
+ * @token: metadata token to load the contraints, can be methodef or typedef.
+ * @container: generic container to load into.
+ *
  * 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.
@@ -5096,11 +5282,8 @@ void
 mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,
                                              MonoGenericContainer *container)
 {
-       guint32 start_row, i, owner;
-       if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
-               return;
-       for (i = 0; i < container->type_argc; i++)
-               get_constraints (image, start_row + i, &container->type_params [i].constraints, container);
+       mono_metadata_load_generic_param_constraints_full (image, token, container);
+       /*FIXME this function can potentially exit with a pending loader error and cause all sort of havok */
 }
 
 /*
@@ -5117,7 +5300,7 @@ mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,
  *
  * Returns: NULL if @token is not a generic type or method definition or the new generic container.
  *
- * LOCKING: Assumes the loader lock is held.
+ * LOCKING: Acquires the loader lock
  *
  */
 MonoGenericContainer *
@@ -5127,7 +5310,7 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericC
        guint32 cols [MONO_GENERICPARAM_SIZE];
        guint32 i, owner = 0, n;
        MonoGenericContainer *container;
-       MonoGenericParam *params;
+       MonoGenericParamFull *params;
        MonoGenericContext *context;
 
        if (!(i = mono_metadata_get_generic_param_row (image, token, &owner)))
@@ -5135,24 +5318,27 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericC
        mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
        params = NULL;
        n = 0;
-       container = mono_mempool_alloc0 (image->mempool, sizeof (MonoGenericContainer));
+       container = mono_image_alloc0 (image, sizeof (MonoGenericContainer));
+       container->image = image;
        do {
                n++;
-               params = g_realloc (params, sizeof (MonoGenericParam) * n);
-               params [n - 1].owner = container;
-               params [n - 1].pklass = NULL;
-               params [n - 1].flags = cols [MONO_GENERICPARAM_FLAGS];
-               params [n - 1].num = cols [MONO_GENERICPARAM_NUMBER];
-               params [n - 1].name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
-               params [n - 1].constraints = NULL;
+               params = g_realloc (params, sizeof (MonoGenericParamFull) * n);
+               memset (&params [n - 1], 0, sizeof (MonoGenericParamFull));
+               params [n - 1].param.owner = container;
+               params [n - 1].param.num = cols [MONO_GENERICPARAM_NUMBER];
+               params [n - 1].info.token = i | MONO_TOKEN_GENERIC_PARAM;
+               params [n - 1].info.flags = cols [MONO_GENERICPARAM_FLAGS];
+               params [n - 1].info.name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
+               if (params [n - 1].param.num != n - 1)
+                       g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i);
                if (++i > tdef->rows)
                        break;
                mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
        } while (cols [MONO_GENERICPARAM_OWNER] == owner);
 
        container->type_argc = n;
-       container->type_params = mono_mempool_alloc0 (image->mempool, sizeof (MonoGenericParam) * n);
-       memcpy (container->type_params, params, sizeof (MonoGenericParam) * n);
+       container->type_params = mono_image_alloc0 (image, sizeof (MonoGenericParamFull) * n);
+       memcpy (container->type_params, params, sizeof (MonoGenericParamFull) * n);
        g_free (params);
        container->parent = parent_container;
 
@@ -5187,7 +5373,7 @@ mono_get_shared_generic_inst (MonoGenericContainer *container)
                MonoType *t = &helper [i];
 
                t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
-               t->data.generic_param = &container->type_params [i];
+               t->data.generic_param = mono_generic_container_get_param (container, i);
 
                type_argv [i] = t;
        }
@@ -5200,43 +5386,95 @@ mono_get_shared_generic_inst (MonoGenericContainer *container)
        return nginst;
 }
 
+/**
+ * mono_type_is_byref:
+ * @type: the MonoType operated on
+ *
+ * Returns: #TRUE if @type represents a type passed by reference,
+ * #FALSE otherwise.
+ */
 gboolean
 mono_type_is_byref (MonoType *type)
 {
        return type->byref;
 }
 
+/**
+ * mono_type_get_type:
+ * @type: the MonoType operated on
+ *
+ * Returns: the IL type value for @type. This is one of the MonoTypeEnum
+ * enum members like MONO_TYPE_I4 or MONO_TYPE_STRING.
+ */
 int
 mono_type_get_type (MonoType *type)
 {
        return type->type;
 }
 
-/* For MONO_TYPE_FNPTR */
+/**
+ * mono_type_get_signature:
+ * @type: the MonoType operated on
+ *
+ * It is only valid to call this function if @type is a MONO_TYPE_FNPTR.
+ *
+ * Returns: the MonoMethodSignature pointer that describes the signature
+ * of the function pointer @type represents.
+ */
 MonoMethodSignature*
 mono_type_get_signature (MonoType *type)
 {
+       g_assert (type->type == MONO_TYPE_FNPTR);
        return type->data.method;
 }
 
-/* For MONO_TYPE_CLASS, VALUETYPE */
+/**
+ * mono_type_get_class:
+ * @type: the MonoType operated on
+ *
+ * It is only valid to call this function if @type is a MONO_TYPE_CLASS or a
+ * MONO_TYPE_VALUETYPE. For more general functionality, use mono_class_from_mono_type (),
+ * instead
+ *
+ * Returns: the MonoClass pointer that describes the class that @type represents.
+ */
 MonoClass*
 mono_type_get_class (MonoType *type)
 {
+       /* FIXME: review the runtime users before adding the assert here */
        return type->data.klass;
 }
 
-/* For MONO_TYPE_ARRAY */
+/**
+ * mono_type_get_array_type:
+ * @type: the MonoType operated on
+ *
+ * It is only valid to call this function if @type is a MONO_TYPE_ARRAY.
+ *
+ * Returns: a MonoArrayType struct describing the array type that @type
+ * represents. The info includes details such as rank, array element type
+ * and the sizes and bounds of multidimensional arrays.
+ */
 MonoArrayType*
 mono_type_get_array_type (MonoType *type)
 {
        return type->data.array;
 }
 
-/* For MONO_TYPE_PTR */
+/**
+ * mono_type_get_ptr_type:
+ * @type: the MonoType operated on
+ *
+ * It is only valid to call this function if @type is a MONO_TYPE_PTR.
+ * instead
+ *
+ * Returns: the MonoType pointer that describes the type that @type
+ * represents a pointer to.
+ */
 MonoType*
 mono_type_get_ptr_type (MonoType *type)
 {
+       g_assert (type->type == MONO_TYPE_PTR);
        return type->data.type;
 }
 
@@ -5347,8 +5585,8 @@ mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent *e
                return event;
 
        gtd = event->parent->generic_class->container_class;
-       offset = event - event->parent->events;
-       return gtd->events + offset;
+       offset = event - event->parent->ext->events;
+       return gtd->ext->events + offset;
 }
 
 /*
@@ -5365,7 +5603,7 @@ mono_metadata_get_corresponding_property_from_generic_type_definition (MonoPrope
                return property;
 
        gtd = property->parent->generic_class->container_class;
-       offset = property - property->parent->properties;
-       return gtd->properties + offset;
+       offset = property - property->parent->ext->properties;
+       return gtd->ext->properties + offset;
 }