This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mono / metadata / metadata.c
index 96c1fa26754a6e7504ab439c635e05c84009b32a..3d44463cde90be1fab9068944735fdeb6b6dd1ab 100644 (file)
@@ -17,6 +17,8 @@
 #include "mono-endian.h"
 #include "cil-coff.h"
 #include "tokentype.h"
+#include "metadata-internals.h"
+#include "class-internals.h"
 #include "private.h"
 #include "class.h"
 
@@ -35,7 +37,7 @@ static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, const cha
  * information might refer to different tables.
  */
 
-static MonoMetaTable AssemblySchema [] = {
+const static MonoMetaTable AssemblySchema [] = {
        { MONO_MT_UINT32,     "HashId" },
        { MONO_MT_UINT16,     "Major" },  
        { MONO_MT_UINT16,     "Minor" },
@@ -48,19 +50,19 @@ static MonoMetaTable AssemblySchema [] = {
        { MONO_MT_END, NULL }
 };
        
-static MonoMetaTable AssemblyOSSchema [] = {
+const static MonoMetaTable AssemblyOSSchema [] = {
        { MONO_MT_UINT32,     "OSPlatformID" },
        { MONO_MT_UINT32,     "OSMajor" },
        { MONO_MT_UINT32,     "OSMinor" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable AssemblyProcessorSchema [] = {
+const static MonoMetaTable AssemblyProcessorSchema [] = {
        { MONO_MT_UINT32,     "Processor" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable AssemblyRefSchema [] = {
+const static MonoMetaTable AssemblyRefSchema [] = {
        { MONO_MT_UINT16,     "Major" },
        { MONO_MT_UINT16,     "Minor" },
        { MONO_MT_UINT16,     "Build" },
@@ -73,7 +75,7 @@ static MonoMetaTable AssemblyRefSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable AssemblyRefOSSchema [] = {
+const static MonoMetaTable AssemblyRefOSSchema [] = {
        { MONO_MT_UINT32,     "OSPlatformID" },
        { MONO_MT_UINT32,     "OSMajorVersion" },
        { MONO_MT_UINT32,     "OSMinorVersion" },
@@ -81,20 +83,20 @@ static MonoMetaTable AssemblyRefOSSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable AssemblyRefProcessorSchema [] = {
+const static MonoMetaTable AssemblyRefProcessorSchema [] = {
        { MONO_MT_UINT32,     "Processor" },
        { MONO_MT_TABLE_IDX,  "AssemblyRef:AssemblyRef" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable ClassLayoutSchema [] = {
+const static MonoMetaTable ClassLayoutSchema [] = {
        { MONO_MT_UINT16,     "PackingSize" },
        { MONO_MT_UINT32,     "ClassSize" },
        { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ConstantSchema [] = {
+const static MonoMetaTable ConstantSchema [] = {
        { MONO_MT_UINT8,      "Type" },
        { MONO_MT_UINT8,      "PaddingZero" },
        { MONO_MT_CONST_IDX,  "Parent" },
@@ -102,34 +104,34 @@ static MonoMetaTable ConstantSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable CustomAttributeSchema [] = {
+const static MonoMetaTable CustomAttributeSchema [] = {
        { MONO_MT_HASCAT_IDX, "Parent" },
        { MONO_MT_CAT_IDX,    "Type" },
        { MONO_MT_BLOB_IDX,   "Value" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable DeclSecuritySchema [] = {
+const static MonoMetaTable DeclSecuritySchema [] = {
        { MONO_MT_UINT16,     "Action" },
        { MONO_MT_HASDEC_IDX, "Parent" },
        { MONO_MT_BLOB_IDX,   "PermissionSet" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable EventMapSchema [] = {
+const static MonoMetaTable EventMapSchema [] = {
        { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
        { MONO_MT_TABLE_IDX,  "EventList:Event" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable EventSchema [] = {
+const static MonoMetaTable EventSchema [] = {
        { MONO_MT_UINT16,     "EventFlags#EventAttribute" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_TABLE_IDX,  "EventType" }, /* TypeDef or TypeRef */
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable ExportedTypeSchema [] = {
+const static MonoMetaTable ExportedTypeSchema [] = {
        { MONO_MT_UINT32,     "Flags" },
        { MONO_MT_TABLE_IDX,  "TypeDefId" },
        { MONO_MT_STRING_IDX, "TypeName" },
@@ -138,37 +140,37 @@ static MonoMetaTable ExportedTypeSchema [] = {
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable FieldSchema [] = {
+const static MonoMetaTable FieldSchema [] = {
        { MONO_MT_UINT16,     "Flags" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_BLOB_IDX,   "Signature" },
        { MONO_MT_END, NULL }   
 };
-static MonoMetaTable FieldLayoutSchema [] = {
+const static MonoMetaTable FieldLayoutSchema [] = {
        { MONO_MT_UINT32,     "Offset" },
        { MONO_MT_TABLE_IDX,  "Field:Field" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable FieldMarshalSchema [] = {
+const static MonoMetaTable FieldMarshalSchema [] = {
        { MONO_MT_HFM_IDX,    "Parent" },
        { MONO_MT_BLOB_IDX,   "NativeType" },
        { MONO_MT_END, NULL }   
 };
-static MonoMetaTable FieldRVASchema [] = {
+const static MonoMetaTable FieldRVASchema [] = {
        { MONO_MT_UINT32,     "RVA" },
        { MONO_MT_TABLE_IDX,  "Field:Field" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable FileSchema [] = {
+const static MonoMetaTable FileSchema [] = {
        { MONO_MT_UINT32,     "Flags" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_BLOB_IDX,   "Value" }, 
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ImplMapSchema [] = {
+const static MonoMetaTable ImplMapSchema [] = {
        { MONO_MT_UINT16,     "MappingFlag" },
        { MONO_MT_MF_IDX,     "MemberForwarded" },
        { MONO_MT_STRING_IDX, "ImportName" },
@@ -176,13 +178,13 @@ static MonoMetaTable ImplMapSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable InterfaceImplSchema [] = {
+const static MonoMetaTable InterfaceImplSchema [] = {
        { MONO_MT_TABLE_IDX,  "Class:TypeDef" }, 
        { MONO_MT_TDOR_IDX,  "Interface=TypeDefOrRef" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ManifestResourceSchema [] = {
+const static MonoMetaTable ManifestResourceSchema [] = {
        { MONO_MT_UINT32,     "Offset" },
        { MONO_MT_UINT32,     "Flags" },
        { MONO_MT_STRING_IDX, "Name" },
@@ -190,14 +192,14 @@ static MonoMetaTable ManifestResourceSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable MemberRefSchema [] = {
+const static MonoMetaTable MemberRefSchema [] = {
        { MONO_MT_MRP_IDX,    "Class" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_BLOB_IDX,   "Signature" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable MethodSchema [] = {
+const static MonoMetaTable MethodSchema [] = {
        { MONO_MT_UINT32,     "RVA" },
        { MONO_MT_UINT16,     "ImplFlags#MethodImplAttributes" },
        { MONO_MT_UINT16,     "Flags#MethodAttribute" },
@@ -207,21 +209,21 @@ static MonoMetaTable MethodSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable MethodImplSchema [] = {
+const static MonoMetaTable MethodImplSchema [] = {
        { MONO_MT_TABLE_IDX,  "Class:TypeDef" },
        { MONO_MT_MDOR_IDX,   "MethodBody" },
        { MONO_MT_MDOR_IDX,   "MethodDeclaration" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable MethodSemanticsSchema [] = {
+const static MonoMetaTable MethodSemanticsSchema [] = {
        { MONO_MT_UINT16,     "MethodSemantic" },
        { MONO_MT_TABLE_IDX,  "Method:Method" },
        { MONO_MT_HS_IDX,     "Association" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ModuleSchema [] = {
+const static MonoMetaTable ModuleSchema [] = {
        { MONO_MT_UINT16,     "Generation" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_GUID_IDX,   "MVID" },
@@ -230,43 +232,43 @@ static MonoMetaTable ModuleSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ModuleRefSchema [] = {
+const static MonoMetaTable ModuleRefSchema [] = {
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable NestedClassSchema [] = {
+const static MonoMetaTable NestedClassSchema [] = {
        { MONO_MT_TABLE_IDX,  "NestedClass:TypeDef" },
        { MONO_MT_TABLE_IDX,  "EnclosingClass:TypeDef" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ParamSchema [] = {
+const static MonoMetaTable ParamSchema [] = {
        { MONO_MT_UINT16,     "Flags" },
        { MONO_MT_UINT16,     "Sequence" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable PropertySchema [] = {
+const static MonoMetaTable PropertySchema [] = {
        { MONO_MT_UINT16,     "Flags" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_BLOB_IDX,   "Type" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable PropertyMapSchema [] = {
+const static MonoMetaTable PropertyMapSchema [] = {
        { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
        { MONO_MT_TABLE_IDX,  "PropertyList:Property" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable StandaloneSigSchema [] = {
+const static MonoMetaTable StandaloneSigSchema [] = {
        { MONO_MT_BLOB_IDX,   "Signature" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable TypeDefSchema [] = {
+const static MonoMetaTable TypeDefSchema [] = {
        { MONO_MT_UINT32,     "Flags" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_STRING_IDX, "Namespace" },
@@ -276,20 +278,44 @@ static MonoMetaTable TypeDefSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable TypeRefSchema [] = {
+const static MonoMetaTable TypeRefSchema [] = {
        { MONO_MT_RS_IDX,     "ResolutionScope=ResolutionScope" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_STRING_IDX, "Namespace" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable TypeSpecSchema [] = {
+const static MonoMetaTable TypeSpecSchema [] = {
        { MONO_MT_BLOB_IDX,   "Signature" },
        { MONO_MT_END, NULL }
 };
 
-static struct {
-       MonoMetaTable *table;
+const static MonoMetaTable GenericParamSchema [] = {
+       { MONO_MT_UINT16,     "Number" },
+       { MONO_MT_UINT16,     "Flags" },
+       { MONO_MT_TABLE_IDX,  "Owner" }, /* TypeDef or MethodDef */
+       { MONO_MT_STRING_IDX, "Name" },
+
+       /* soon to be removed */
+       { MONO_MT_TABLE_IDX,  "Kind" }, 
+       
+       { MONO_MT_END, NULL }
+};
+
+const static MonoMetaTable MethodSpecSchema [] = {
+       { MONO_MT_MDOR_IDX,   "Method" },
+       { MONO_MT_BLOB_IDX,   "Signature" },
+       { MONO_MT_END, NULL }
+};
+
+const static MonoMetaTable GenericParamConstraintSchema [] = {
+       { MONO_MT_TABLE_IDX,  "GenericParam" },
+       { MONO_MT_TDOR_IDX,   "Constraint" },
+       { MONO_MT_END, NULL }
+};
+
+const static struct {
+       const MonoMetaTable *table;
        const char    *name;
 } tables [] = {
        /*  0 */ { ModuleSchema,               "Module" },
@@ -334,8 +360,9 @@ static struct {
        /* 27 */ { ExportedTypeSchema,         "ExportedType" },
        /* 28 */ { ManifestResourceSchema,     "ManifestResource" },
        /* 29 */ { NestedClassSchema,          "NestedClass" },
-       /* 2A */ { NULL,                       NULL },
-       /* 2B */ { NULL,                       NULL },
+       /* 2A */ { GenericParamSchema,         "GenericParam" },
+       /* 2B */ { MethodSpecSchema,           "MethodSpec" },
+       /* 2C */ { GenericParamConstraintSchema, "GenericParamConstraint" },
 };
 
 /**
@@ -347,7 +374,7 @@ static struct {
 const char *
 mono_meta_table_name (int table)
 {
-       if ((table < 0) || (table > 0x29))
+       if ((table < 0) || (table > 0x2c))
                return "";
        
        return tables [table].name;
@@ -386,7 +413,7 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
        int size = 0, field_size;
        int i, n, code;
        int shift = 0;
-       MonoMetaTable *table = tables [tableindex].table;
+       const MonoMetaTable *table = tables [tableindex].table;
 
        for (i = 0; (code = table [i].code) != MONO_MT_END; i++){
                switch (code){
@@ -435,7 +462,8 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                                break;
                        case MONO_TABLE_EXPORTEDTYPE:
                                g_assert (i == 1);
-                               field_size = idx_size (MONO_TABLE_TYPEDEF); break;
+                               /* the index is in another metadata file, so it must be 4 */
+                               field_size = 4; break;
                        case MONO_TABLE_FIELDLAYOUT:
                                g_assert (i == 1);
                                field_size = idx_size (MONO_TABLE_FIELD); break;
@@ -468,12 +496,26 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                        case MONO_TABLE_TYPEDEF:
                                g_assert (i == 4 || i == 5);
                                field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
-                                       idx_size(MONO_TABLE_METHOD); 
+                                       idx_size(MONO_TABLE_METHOD);
+                       case MONO_TABLE_GENERICPARAM:
+                               g_assert (i == 2 || i == 4 || i == 5);
+                               if (i == 2)
+                                       field_size = MAX (idx_size (MONO_TABLE_METHOD), idx_size (MONO_TABLE_TYPEDEF));
+                               else if (i == 4)
+                                       field_size = idx_size (MONO_TABLE_TYPEDEF);
+                               else if (i == 5)
+                                       field_size = idx_size (MONO_TABLE_TYPEDEF);
+                               break;
+
+                       case MONO_TABLE_GENERICPARAMCONSTRAINT:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_GENERICPARAM);
                                break;
+                               
                        default:
                                g_assert_not_reached ();
                        }
-                       if (field_size != idx_size (tableindex))
+                       if (tableindex != MONO_TABLE_EXPORTEDTYPE && field_size != idx_size (tableindex))
                                g_warning ("size changed (%d to %d)", idx_size (tableindex), field_size);
                        
                        break;
@@ -733,7 +775,7 @@ mono_metadata_locate_token (MonoImage *meta, guint32 token)
  *
  * Returns the MonoMetaTable structure for table @table
  */
-MonoMetaTable *
+const MonoMetaTable *
 mono_metadata_get_table (MonoMetaTableEnum table)
 {
        int x = (int) table;
@@ -804,7 +846,11 @@ mono_metadata_guid_heap (MonoImage *meta, guint32 index)
 static const char *
 dword_align (const char *ptr)
 {
+#if SIZEOF_VOID_P == 8
+       return (const char *) (((guint64) (ptr + 3)) & ~3);
+#else
        return (const char *) (((guint32) (ptr + 3)) & ~3);
+#endif
 }
 
 /**
@@ -1011,8 +1057,10 @@ mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
 {
        int i;
        MonoArrayType *array = g_new0 (MonoArrayType, 1);
+       MonoType *etype;
        
-       array->type = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       etype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       array->eklass = mono_class_from_mono_type (etype);
        array->rank = mono_metadata_decode_value (ptr, &ptr);
 
        array->numsizes = mono_metadata_decode_value (ptr, &ptr);
@@ -1041,7 +1089,6 @@ mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
 void
 mono_metadata_free_array (MonoArrayType *array)
 {
-       mono_metadata_free_type (array->type);
        g_free (array->sizes);
        g_free (array->lobounds);
        g_free (array);
@@ -1091,8 +1138,6 @@ builtin_types[] = {
        {{NULL}, 0,     MONO_TYPE_I,       0,     1,     0},
        {{NULL}, 0,     MONO_TYPE_U,       0,     0,     0},
        {{NULL}, 0,     MONO_TYPE_U,       0,     1,     0},
-       {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     0,     0},
-       {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     1,     0}
 };
 
 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
@@ -1121,6 +1166,22 @@ mono_type_equal (gconstpointer ka, gconstpointer kb)
        return 1;
 }
 
+/**
+ * mono_metadata_init:
+ *
+ *  Initialize the global variables of this module.
+ */
+void
+mono_metadata_init (void)
+{
+       int i;
+
+       type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
+
+       for (i = 0; i < NBUILTIN_TYPES (); ++i)
+               g_hash_table_insert (type_cache, &builtin_types [i], &builtin_types [i]);
+}
+
 /*
  * mono_metadata_parse_type:
  * @m: metadata context
@@ -1141,74 +1202,88 @@ MonoType*
 mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs, const char *ptr, const char **rptr)
 {
        MonoType *type, *cached;
+       gboolean byref = FALSE;
+       gboolean pinned = FALSE;
+       const char *tmp_ptr;
+       int count = 0;
+       gboolean found;
 
-       if (!type_cache) {
-               int i;
-               type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
-
-               for (i = 0; i < NBUILTIN_TYPES (); ++i)
-                       g_hash_table_insert (type_cache, &builtin_types [i], &builtin_types [i]);
-       }
-
-       switch (mode) {
-       case MONO_PARSE_MOD_TYPE:
-       case MONO_PARSE_PARAM:
-       case MONO_PARSE_RET:
-       case MONO_PARSE_LOCAL: /* should not have modifiers according to the spec, but ms tools disagree */
-       case MONO_PARSE_FIELD: {
-               /* count the modifiers */
-               const char *tmp_ptr = ptr;
-               int count = 0;
-               while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
-                       count++;
-               if (count) {
-                       type = g_malloc0 (sizeof (MonoType) + (count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
-                       type->num_mods = count;
-                       if (count > 64)
-                               g_warning ("got more than 64 modifiers in type");
-                       /* save them this time */
-                       count = 0;
-                       while (mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr))
-                               count++;
+       /*
+        * According to the spec, custom modifiers should come before the byref
+        * flag, but the IL produced by ilasm from the following signature:
+        *   object modopt(...) &
+        * starts with a byref flag, followed by the modifiers. (bug #49802)
+        * Also, this type seems to be different from 'object & modopt(...)'. Maybe
+        * it would be better to treat byref as real type constructor instead of
+        * a modifier...
+        * Also, pinned should come before anything else, but some MSV++ produced
+        * assemblies violate this (#bug 61990).
+        */
+
+       /* Count the modifiers first */
+       tmp_ptr = ptr;
+       found = TRUE;
+       while (found) {
+               switch (*tmp_ptr) {
+               case MONO_TYPE_PINNED:
+               case MONO_TYPE_BYREF:
+                       ++tmp_ptr;
                        break;
-               } /* fall through */
+               case MONO_TYPE_CMOD_REQD:
+               case MONO_TYPE_CMOD_OPT:
+                       count ++;
+                       mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
+                       break;
+               default:
+                       found = FALSE;
+               }
        }
-       case MONO_PARSE_TYPE:
+
+       if (count) {
+               type = g_malloc0 (sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
+               type->num_mods = count;
+               if (count > 64)
+                       g_warning ("got more than 64 modifiers in type");
+       }
+       else
                /*
                 * Later we can avoid doing this allocation.
                 */
                type = g_new0 (MonoType, 1);
-               break;
-       default:
-               g_assert_not_reached ();
-       }
-       
-       type->attrs = opt_attrs;
-       if (mode == MONO_PARSE_LOCAL) {
-               /*
-                * check for pinned flag
-                */
-               if (*ptr == MONO_TYPE_PINNED) {
-                       type->pinned = 1;
+
+       /* Parse pinned, byref and custom modifiers */
+       found = TRUE;
+       count = 0;
+       while (found) {
+               switch (*ptr) {
+               case MONO_TYPE_PINNED:
+                       pinned = TRUE;
                        ++ptr;
+                       break;
+               case MONO_TYPE_BYREF:
+                       byref = TRUE;
+                       ++ptr;
+                       break;
+               case MONO_TYPE_CMOD_REQD:
+               case MONO_TYPE_CMOD_OPT:
+                       count ++;
+                       mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
+                       break;
+               default:
+                       found = FALSE;
                }
        }
+       
+       type->attrs = opt_attrs;
+       type->byref = byref;
+       type->pinned = pinned ? 1 : 0;
+
+       do_mono_metadata_parse_type (type, m, ptr, &ptr);
 
-       switch (*ptr) {
-       case MONO_TYPE_BYREF: 
-               if (mode == MONO_PARSE_FIELD)
-                       g_warning ("A field type cannot be byref");
-               type->byref = 1; 
-               ptr++;
-               /* follow through */
-       default:
-               /*if (*ptr == MONO_TYPE_VOID && mode != MONO_PARSE_RET)
-                       g_error ("void not allowed in param");*/
-               do_mono_metadata_parse_type (type, m, ptr, &ptr);
-               break;
-       }
        if (rptr)
                *rptr = ptr;
+
+       /* No need to use locking since nobody is modifying the hash table */
        if (mode != MONO_PARSE_PARAM && !type->num_mods && (cached = g_hash_table_lookup (type_cache, type))) {
                mono_metadata_free_type (type);
                return cached;
@@ -1234,6 +1309,9 @@ mono_metadata_parse_signature (MonoImage *image, guint32 token)
        guint32 sig;
        const char *ptr;
 
+       if (image->dynamic)
+               return mono_lookup_dynamic_token (image, token);
+
        g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
                
        sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
@@ -1250,12 +1328,22 @@ mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
        MonoMethodSignature *sig;
 
        /* later we want to allocate signatures with mempools */
-       sig = g_malloc0 (sizeof (MonoMethodSignature) + (nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+       sig = g_malloc0 (sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
        sig->param_count = nparams;
+       sig->sentinelpos = -1;
 
        return sig;
 }
 
+MonoMethodSignature*
+mono_metadata_signature_dup (MonoMethodSignature *sig)
+{
+       int sigsize;
+
+       sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
+       return g_memdup (sig, sigsize);
+}
+
 /*
  * mono_metadata_parse_method_signature:
  * @m: metadata context
@@ -1273,13 +1361,18 @@ mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, co
        MonoMethodSignature *method;
        int i, ret_attrs = 0, *pattrs = NULL;
        guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
+       guint32 gen_param_count = 0;
 
+       if (*ptr & 0x10)
+               gen_param_count = 1;
        if (*ptr & 0x20)
                hasthis = 1;
        if (*ptr & 0x40)
                explicit_this = 1;
        call_convention = *ptr & 0x0F;
        ptr++;
+       if (gen_param_count)
+               gen_param_count = mono_metadata_decode_value (ptr, &ptr);
        param_count = mono_metadata_decode_value (ptr, &ptr);
        pattrs = g_new0 (int, param_count);
 
@@ -1292,7 +1385,7 @@ mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, co
                if (def < methodt->rows)
                        lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
                else
-                       lastp = paramt->rows;
+                       lastp = paramt->rows + 1;
                for (i = param_index; i < lastp; ++i) {
                        mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
                        if (!cols [MONO_PARAM_SEQUENCE])
@@ -1305,7 +1398,9 @@ mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, co
        method->hasthis = hasthis;
        method->explicit_this = explicit_this;
        method->call_convention = call_convention;
-       method->ret = mono_metadata_parse_type (m, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
+       method->generic_param_count = gen_param_count;
+       if (call_convention != 0xa)
+               method->ret = mono_metadata_parse_type (m, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
 
        if (method->param_count) {
                method->sentinelpos = -1;
@@ -1320,6 +1415,10 @@ mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, co
                        method->params [i] = mono_metadata_parse_type (m, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
                }
        }
+
+       if (def && (method->call_convention == MONO_CALL_VARARG))
+               method->sentinelpos = method->param_count;
+
        g_free (pattrs);
 
        if (rptr)
@@ -1347,6 +1446,97 @@ mono_metadata_free_method_signature (MonoMethodSignature *sig)
        g_free (sig);
 }
 
+static void
+do_mono_metadata_parse_generic_inst (MonoType *type, MonoImage *m, const char *ptr, const char **rptr)
+{
+       MonoGenericInst *ginst = g_new0 (MonoGenericInst, 1);
+       MonoType *cached;
+       int i, count;
+
+       type->data.generic_inst = ginst;
+
+       ginst->context = g_new0 (MonoGenericContext, 1);
+       ginst->context->ginst = ginst;
+
+       ginst->klass = g_new0 (MonoClass, 1);
+
+       ginst->generic_type = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       ginst->type_argc = count = mono_metadata_decode_value (ptr, &ptr);
+       ginst->type_argv = g_new0 (MonoType*, count);
+
+       /*
+        * Create the klass before parsing the type arguments.
+        * This is required to support "recursive" definitions.
+        * See mcs/tests/gen-23.cs for an example.
+        */
+
+       ginst->init_pending = TRUE;
+
+       mono_class_create_generic (ginst);
+
+       for (i = 0; i < ginst->type_argc; i++) {
+               MonoType *t = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+
+               ginst->type_argv [i] = t;
+               if (!ginst->is_open)
+                       ginst->is_open = mono_class_is_open_constructed_type (t);
+       }
+
+
+       if (rptr)
+               *rptr = ptr;
+
+       /*
+        * We may be called multiple times on different metadata to create the same
+        * instantiated type.  This happens for instance if we're part of a method or
+        * local variable signature.
+        *
+        * It's important to return the same MonoGenericInst * for each particualar
+        * instantiation of a generic type (ie "Stack<Int32>") to make static fields
+        * work.
+        *
+        * According to the spec ($26.1.5), a static variable in a generic class
+        * declaration is shared amongst all instances of the same closed constructed
+        * type.
+        */
+
+       cached = g_hash_table_lookup (m->generic_inst_cache, ginst);
+       if (cached) {
+               g_free (ginst->klass);
+               g_free (ginst->type_argv);
+               g_free (ginst);
+
+               type->data.generic_inst = cached->data.generic_inst;
+               return;
+       } else {
+               cached = g_new0 (MonoType, 1);
+               cached->type = MONO_TYPE_GENERICINST;
+               cached->data.generic_inst = ginst;
+
+               g_hash_table_insert (m->generic_inst_cache, ginst, cached);
+
+               mono_stats.generic_instance_count++;
+               mono_stats.generics_metadata_size += sizeof (MonoGenericInst) +
+                       sizeof (MonoGenericContext) +
+                       ginst->type_argc * sizeof (MonoType);
+       }
+
+       ginst->init_pending = FALSE;
+}
+
+static MonoGenericParam *
+mono_metadata_parse_generic_param (MonoImage *m, const char *ptr, const char **rptr)
+{
+       MonoGenericParam *generic_param = g_new0 (MonoGenericParam, 1);
+       
+       generic_param->num = mono_metadata_decode_value (ptr, &ptr);
+
+       if (rptr)
+               *rptr = ptr;
+
+       return generic_param;
+}
+
 /* 
  * do_mono_metadata_parse_type:
  * @type: MonoType to be filled in with the return value
@@ -1393,7 +1583,12 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, const char *ptr, cons
                type->data.klass = mono_class_get (m, token);
                break;
        }
-       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_SZARRAY: {
+               MonoType *etype = mono_metadata_parse_type (m, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+               type->data.klass = mono_class_from_mono_type (etype);
+               mono_metadata_free_type (etype);
+               break;
+       }
        case MONO_TYPE_PTR:
                type->data.type = mono_metadata_parse_type (m, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
                break;
@@ -1403,8 +1598,18 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, const char *ptr, cons
        case MONO_TYPE_ARRAY:
                type->data.array = mono_metadata_parse_array (m, ptr, &ptr);
                break;
+
+       case MONO_TYPE_MVAR:
+       case MONO_TYPE_VAR:
+               type->data.generic_param = mono_metadata_parse_generic_param (m, ptr, &ptr);
+               break;
+
+       case MONO_TYPE_GENERICINST:
+               do_mono_metadata_parse_generic_inst (type, m, ptr, &ptr);
+               break;
+               
        default:
-               g_error ("type 0x%02x not handled in mono_metadata_parse_type", type->type);
+               g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type->type);
        }
        
        if (rptr)
@@ -1423,7 +1628,6 @@ mono_metadata_free_type (MonoType *type)
        if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
                return;
        switch (type->type){
-       case MONO_TYPE_SZARRAY:
        case MONO_TYPE_PTR:
                mono_metadata_free_type (type->data.type);
                break;
@@ -1742,8 +1946,6 @@ typedef struct {
        guint32 result;
 } locator_t;
 
-#define CSIZE(x) (sizeof (x) / 4)
-
 /*
  * How the row locator works.
  *
@@ -1972,37 +2174,33 @@ mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
  * @index: typedef token
  * 
  * Returns: the 1-based index into the TypeDef table of the first type
- * that is nested inside the type described by @index.
- * Retruns 0 if @index doesn't have nested types.
+ * that is nested inside the type described by @index. The search starts at
+ * @start_index.
+ * Returns 0 if no such type is found.
  */
 guint32
-mono_metadata_nesting_typedef (MonoImage *meta, guint32 index)
+mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
 {
        MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
-       locator_t loc;
        guint32 start;
+       guint32 class_index = mono_metadata_token_index (index);
        
        if (!tdef->base)
                return 0;
 
-       loc.idx = mono_metadata_token_index (index);
-       loc.col_idx = MONO_NESTED_CLASS_ENCLOSING;
-       loc.t = tdef;
-
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
-               return 0;
-
-       start = loc.result;
+       start = start_index;
 
-       while (start > 0) {
-               if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
-                       start--;
-               else
+       while (start <= tdef->rows) {
+               if (class_index == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
                        break;
+               else
+                       start++;
        }
 
-       /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
-       return start + 1;
+       if (start > tdef->rows)
+               return 0;
+       else
+               return start;
 }
 
 /*
@@ -2041,8 +2239,58 @@ mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *pac
        return loc.result + 1;
 }
 
+/*
+ * mono_metadata_custom_attrs_from_index:
+ * @meta: metadata context
+ * @index: token representing the parent
+ * 
+ * Returns: the 1-based index into the CustomAttribute table of the first 
+ * attribute which belongs to the metadata object described by @index.
+ * Returns 0 if no such attribute is found.
+ */
+guint32
+mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
+{
+       MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+       locator_t loc;
+       
+       if (!tdef->base)
+               return 0;
+
+       loc.idx = index;
+       loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
+       loc.t = tdef;
+
+       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+               return 0;
+
+       /* Find the first entry by searching backwards */
+       while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_CUSTOM_ATTR_PARENT) == index))
+               loc.result --;
+
+       /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
+       return loc.result + 1;
+}
+
+#ifdef DEBUG
+static void
+mono_backtrace (int limit)
+{
+       void *array[limit];
+       char **names;
+       int i;
+       backtrace (array, limit);
+       names = backtrace_symbols (array, limit);
+       for (i =0; i < limit; ++i) {
+               g_print ("\t%s\n", names [i]);
+       }
+       g_free (names);
+}
+#endif
+
 #ifndef __GNUC__
-#define __alignof__(a) sizeof(a)
+/*#define __alignof__(a) sizeof(a)*/
+#define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
 #endif
 
 /*
@@ -2115,11 +2363,21 @@ mono_type_size (MonoType *t, gint *align)
        case MONO_TYPE_PTR:
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_ARRAY:
-       case MONO_TYPE_TYPEDBYREF: /* we may want to use a struct {MonoType* type, void *data } instead ...*/
+               *align = __alignof__(gpointer);
+               return sizeof (gpointer);
+       case MONO_TYPE_TYPEDBYREF:
+               return mono_class_value_size (mono_defaults.typed_reference_class, align);
+       case MONO_TYPE_GENERICINST: {
+               MonoGenericInst *ginst = t->data.generic_inst;
+               MonoClass *iclass = mono_class_from_mono_type (ginst->generic_type);
+               return mono_type_size (&iclass->byval_arg, align);
+       }
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR:
                *align = __alignof__(gpointer);
                return sizeof (gpointer);
        default:
-               g_error ("type 0x%02x unknown", t->type);
+               g_error ("mono_type_size: type 0x%02x unknown", t->type);
        }
        return 0;
 }
@@ -2164,9 +2422,11 @@ mono_type_stack_size (MonoType *t, gint *align)
        case MONO_TYPE_PTR:
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_ARRAY:
-       case MONO_TYPE_TYPEDBYREF:
                *align = __alignof__(gpointer);
                return sizeof (gpointer);
+       case MONO_TYPE_TYPEDBYREF:
+               *align = __alignof__(gpointer);
+               return sizeof (gpointer) * 3;
        case MONO_TYPE_R4:
                *align = __alignof__(float);
                return sizeof (float);          
@@ -2188,83 +2448,43 @@ mono_type_stack_size (MonoType *t, gint *align)
                        *align = *align + __alignof__(gpointer) - 1;
                        *align &= ~(__alignof__(gpointer) - 1);
 
+                       size += sizeof (gpointer) - 1;
+                       size &= ~(sizeof (gpointer) - 1);
+
                        return size;
                }
        }
+       case MONO_TYPE_GENERICINST: {
+               MonoGenericInst *ginst = t->data.generic_inst;
+               MonoClass *iclass = mono_class_from_mono_type (ginst->generic_type);
+               return mono_type_stack_size (&iclass->byval_arg, align);
+       }
        default:
                g_error ("type 0x%02x unknown", t->type);
        }
        return 0;
 }
 
-/*
- * mono_type_native_stack_size:
- * @t: the type to return the size it uses on the stack
- *
- * Returns: the number of bytes required to hold an instance of this
- * type on the native stack
- */
-int
-mono_type_native_stack_size (MonoType *t, gint *align)
+guint
+mono_metadata_generic_inst_hash (MonoGenericInst *ginst)
 {
-       int tmp;
-
-       g_assert (t != NULL);
-
-       if (!align)
-               align = &tmp;
-
-       if (t->byref) {
-               *align = 4;
-               return 4;
-       }
+       return mono_metadata_type_hash (ginst->generic_type);
+}
 
-       switch (t->type){
-       case MONO_TYPE_BOOLEAN:
-       case MONO_TYPE_CHAR:
-       case MONO_TYPE_I1:
-       case MONO_TYPE_U1:
-       case MONO_TYPE_I2:
-       case MONO_TYPE_U2:
-       case MONO_TYPE_I4:
-       case MONO_TYPE_U4:
-       case MONO_TYPE_I:
-       case MONO_TYPE_U:
-       case MONO_TYPE_STRING:
-       case MONO_TYPE_OBJECT:
-       case MONO_TYPE_CLASS:
-       case MONO_TYPE_SZARRAY:
-       case MONO_TYPE_PTR:
-       case MONO_TYPE_FNPTR:
-       case MONO_TYPE_ARRAY:
-       case MONO_TYPE_TYPEDBYREF:
-               *align = 4;
-               return 4;
-       case MONO_TYPE_R4:
-               *align = 4;
-               return 4;
-       case MONO_TYPE_I8:
-       case MONO_TYPE_U8:
-       case MONO_TYPE_R8:
-               *align = 4;
-               return 8;
-       case MONO_TYPE_VALUETYPE: {
-               guint32 size;
+gboolean
+mono_metadata_generic_inst_equal (MonoGenericInst *g1, MonoGenericInst *g2)
+{
+       int i;
 
-               if (t->data.klass->enumtype)
-                       return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
-               else {
-                       size = mono_class_native_size (t->data.klass, align);
-                       *align = *align + 3;
-                       *align &= ~3;
-                       
-                       return size;
-               }
-       }
-       default:
-               g_error ("type 0x%02x unknown", t->type);
+       if (g1->type_argc != g2->type_argc)
+               return FALSE;
+       if (!mono_metadata_type_equal (g1->generic_type, g2->generic_type))
+               return FALSE;
+       for (i = 0; i < g1->type_argc; ++i) {
+               if (!mono_metadata_type_equal (g1->type_argv [i], g2->type_argv [i]))
+                       return FALSE;
        }
-       return 0;
+       return TRUE;
 }
 
 /*
@@ -2282,15 +2502,33 @@ 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 << 7 | g_str_hash (t1->data.klass->name);
+               return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
        case MONO_TYPE_PTR:
-       case MONO_TYPE_SZARRAY:
-               return hash << 7 | mono_metadata_type_hash (t1->data.type);
+               return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
+       case MONO_TYPE_ARRAY:
+               return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
+       case MONO_TYPE_GENERICINST:
+               return ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (t1->data.generic_inst);
        }
        return hash;
 }
 
+static gboolean
+mono_metadata_class_equal (MonoClass *c1, MonoClass *c2)
+{
+       if (c1 == c2)
+               return TRUE;
+       if (c1->generic_inst && c2->generic_inst)
+               return mono_metadata_generic_inst_equal (c1->generic_inst, c2->generic_inst);
+       if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
+               return c1->byval_arg.data.generic_param->num == c2->byval_arg.data.generic_param->num;
+       if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR))
+               return c1->byval_arg.data.generic_param->num == c2->byval_arg.data.generic_param->num;
+       return FALSE;
+}
+
 /*
  * mono_metadata_type_equal:
  * @t1: a type
@@ -2324,17 +2562,24 @@ mono_metadata_type_equal (MonoType *t1, MonoType *t2)
        case MONO_TYPE_I:
        case MONO_TYPE_U:
        case MONO_TYPE_OBJECT:
+       case MONO_TYPE_TYPEDBYREF:
                return TRUE;
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_CLASS:
-               return t1->data.klass == t2->data.klass;
-       case MONO_TYPE_PTR:
        case MONO_TYPE_SZARRAY:
+               return mono_metadata_class_equal (t1->data.klass, t2->data.klass);
+       case MONO_TYPE_PTR:
                return mono_metadata_type_equal (t1->data.type, t2->data.type);
        case MONO_TYPE_ARRAY:
                if (t1->data.array->rank != t2->data.array->rank)
                        return FALSE;
-               return mono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
+               return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass);
+       case MONO_TYPE_GENERICINST:
+               return mono_metadata_generic_inst_equal (t1->data.generic_inst,
+                                                        t2->data.generic_inst);
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR:
+               return t1->data.generic_param->num == t2->data.generic_param->num;
        default:
                g_error ("implement type compare for %0x!", t1->type);
                return FALSE;
@@ -2365,9 +2610,9 @@ mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *s
                MonoType *p1 = sig1->params[i];
                MonoType *p2 = sig2->params[i];
                
-               //if (p1->attrs != p2->attrs)
-               //      return FALSE;
-               
+               /if (p1->attrs != p2->attrs)
+                       return FALSE;
+               */
                if (!mono_metadata_type_equal (p1, p2))
                        return FALSE;
        }
@@ -2403,9 +2648,9 @@ mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
 {
        char *p = buf;
        
-       if (value <= 127)
+       if (value < 0x80)
                *p++ = value;
-       else if (value <= 16384) {
+       else if (value < 0x4000) {
                p [0] = 0x80 | (value >> 8);
                p [1] = value & 0xff;
                p += 2;
@@ -2474,17 +2719,8 @@ mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint
        if (marshal_spec) {
                const char *p;
                
-               tdef = &meta->tables [MONO_TABLE_FIELDMARSHAL];
-
-               loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
-               loc.t = tdef;
-               loc.idx = (loc.idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
-
-               if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
-                       p = mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
+               if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
                        *marshal_spec = mono_metadata_parse_marshal_spec (meta, p);
-               } else {
-                       *marshal_spec = NULL;
                }
        }
 
@@ -2494,29 +2730,30 @@ mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint
  * mono_metadata_get_constant_index:
  * @meta: the Image the field is defined in
  * @index: the token that may have a row defined in the constants table
+ * @hint: possible position for the row
  *
  * @token must be a FieldDef, ParamDef or PropertyDef token.
  *
- * Returns: the index into the Constsnts table or 0 if not found.
+ * Returns: the index into the Constants table or 0 if not found.
  */
 guint32
-mono_metadata_get_constant_index (MonoImage *meta, guint32 token)
+mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
 {
        MonoTableInfo *tdef;
        locator_t loc;
        guint32 index = mono_metadata_token_index (token);
 
        tdef = &meta->tables [MONO_TABLE_CONSTANT];
-       index <<= HASCONSTANT_BITS;
+       index <<= MONO_HASCONSTANT_BITS;
        switch (mono_metadata_token_table (token)) {
        case MONO_TABLE_FIELD:
-               index |= HASCONSTANT_FIEDDEF;
+               index |= MONO_HASCONSTANT_FIEDDEF;
                break;
        case MONO_TABLE_PARAM:
-               index |= HASCONSTANT_PARAM;
+               index |= MONO_HASCONSTANT_PARAM;
                break;
        case MONO_TABLE_PROPERTY:
-               index |= HASCONSTANT_PROPERTY;
+               index |= MONO_HASCONSTANT_PROPERTY;
                break;
        default:
                g_warning ("Not a valid token for the constant table: 0x%08x", token);
@@ -2526,6 +2763,9 @@ mono_metadata_get_constant_index (MonoImage *meta, guint32 token)
        loc.col_idx = MONO_CONSTANT_PARENT;
        loc.t = tdef;
 
+       if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
+               return hint;
+
        if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
                return loc.result + 1;
        }
@@ -2594,7 +2834,7 @@ mono_metadata_methods_from_event   (MonoImage *meta, guint32 index, guint *end_i
 
        loc.t = msemt;
        loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
-       loc.idx = ((index + 1) << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT; /* Method association coded index */
+       loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
 
        if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
                return 0;
@@ -2682,7 +2922,7 @@ mono_metadata_methods_from_property   (MonoImage *meta, guint32 index, guint *en
 
        loc.t = msemt;
        loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
-       loc.idx = ((index + 1) << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY; /* Method association coded index */
+       loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
 
        if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
                return 0;
@@ -2719,7 +2959,7 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
 
        loc.t = tdef;
        loc.col_idx = MONO_IMPLMAP_MEMBER;
-       loc.idx = ((method_idx + 1) << MEMBERFORWD_BITS) | MEMBERFORWD_METHODDEF;
+       loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
 
        if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return 0;
@@ -2744,12 +2984,31 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
        guint32 len;
        MonoType *type;
 
+       mono_loader_lock ();
+
+       if ((type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)))) {
+               mono_loader_unlock ();
+               return type;
+       }
+
        t = &image->tables [MONO_TABLE_TYPESPEC];
        
        mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
        ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
        len = mono_metadata_decode_value (ptr, &ptr);
-       type = mono_metadata_parse_type (image, MONO_PARSE_TYPE, 0, ptr, &ptr);
+
+       type = g_new0 (MonoType, 1);
+
+       g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type);
+
+       if (*ptr == MONO_TYPE_BYREF) {
+               type->byref = 1; 
+               ptr++;
+       }
+
+       do_mono_metadata_parse_type (type, image, ptr, &ptr);
+
+       mono_loader_unlock ();
 
        return type;
 }
@@ -2770,21 +3029,37 @@ mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
 
        if (res->native == MONO_NATIVE_LPARRAY) {
                if (ptr - start <= len)
-                       res->elem_type = *ptr++;
+                       res->data.array_data.elem_type = *ptr++;
                if (ptr - start <= len)
-                       res->param_num = mono_metadata_decode_value (ptr, &ptr);
+                       res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr);
                if (ptr - start <= len)
-                       res->num_elem = mono_metadata_decode_value (ptr, &ptr);
+                       res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
        } 
 
        if (res->native == MONO_NATIVE_BYVALTSTR) {
                if (ptr - start <= len)
-                       res->num_elem = mono_metadata_decode_value (ptr, &ptr);
+                       res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
        }
 
        if (res->native == MONO_NATIVE_BYVALARRAY) {
                if (ptr - start <= len)
-                       res->num_elem = mono_metadata_decode_value (ptr, &ptr);
+                       res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
+       }
+       
+       if (res->native == MONO_NATIVE_CUSTOM) {
+               /* skip unused type guid */
+               len = mono_metadata_decode_value (ptr, &ptr);
+               ptr += len;
+               /* skip unused native type name */
+               len = mono_metadata_decode_value (ptr, &ptr);
+               ptr += len;
+               /* read custom marshaler type name */
+               len = mono_metadata_decode_value (ptr, &ptr);
+               res->data.custom_data.custom_name = g_strndup (ptr, len);               
+               ptr += len;
+               /* read cookie string */
+               len = mono_metadata_decode_value (ptr, &ptr);
+               res->data.custom_data.cookie = g_strndup (ptr, len);
        }
 
        return res;
@@ -2816,8 +3091,9 @@ handle_enum:
                        case MONO_NATIVE_BOOLEAN:
                                *conv = MONO_MARSHAL_CONV_BOOL_I4;
                                return MONO_NATIVE_BOOLEAN;
+                       case MONO_NATIVE_I1:
                        case MONO_NATIVE_U1:
-                               return MONO_NATIVE_U1;
+                               return mspec->native;
                        default:
                                g_error ("cant marshal bool to native type %02x", mspec->native);
                        }
@@ -2913,11 +3189,23 @@ handle_enum:
                        case MONO_NATIVE_IUNKNOWN:
                                *conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN;
                                return MONO_NATIVE_IUNKNOWN;
+                       case MONO_NATIVE_FUNC:
+                               if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
+                                                                                        type->data.klass == mono_defaults.delegate_class || 
+                                                                                        type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
+                                       *conv = MONO_MARSHAL_CONV_DEL_FTN;
+                                       return MONO_NATIVE_FUNC;
+                               }
+                               else
+                                       /* Fall through */
+                                       ;
                        default:
                                g_error ("cant marshal object as native type %02x", mspec->native);
                        }
                }
-               if (type->data.klass->parent == mono_defaults.multicastdelegate_class) {
+               if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
+                                            type->data.klass == mono_defaults.delegate_class || 
+                                            type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
                        *conv = MONO_MARSHAL_CONV_DEL_FTN;
                        return MONO_NATIVE_FUNC;
                }
@@ -2932,86 +3220,6 @@ handle_enum:
        return MONO_NATIVE_MAX;
 }
 
-gint32
-mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align, 
-                       gboolean as_field, gboolean unicode)
-{
-       MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
-       MonoClass *klass;
-
-       switch (native_type) {
-       case MONO_NATIVE_BOOLEAN:
-               *align = 4;
-               return 4;
-       case MONO_NATIVE_I1:
-       case MONO_NATIVE_U1:
-               *align = 1;
-               return 1;
-       case MONO_NATIVE_I2:
-       case MONO_NATIVE_U2:
-               *align = 2;
-               return 2;
-       case MONO_NATIVE_I4:
-       case MONO_NATIVE_U4:
-       case MONO_NATIVE_ERROR:
-               *align = 4;
-               return 4;
-       case MONO_NATIVE_I8:
-       case MONO_NATIVE_U8:
-               *align = 4;
-               return 8;
-       case MONO_NATIVE_R4:
-               *align = 4;
-               return 4;
-       case MONO_NATIVE_R8:
-               *align = 4;
-               return 8;
-       case MONO_NATIVE_INT:
-       case MONO_NATIVE_UINT:
-       case MONO_NATIVE_LPSTR:
-       case MONO_NATIVE_LPWSTR:
-       case MONO_NATIVE_LPTSTR:
-       case MONO_NATIVE_BSTR:
-       case MONO_NATIVE_ANSIBSTR:
-       case MONO_NATIVE_TBSTR:
-       case MONO_NATIVE_LPARRAY:
-       case MONO_NATIVE_SAFEARRAY:
-       case MONO_NATIVE_IUNKNOWN:
-       case MONO_NATIVE_IDISPATCH:
-       case MONO_NATIVE_INTERFACE:
-       case MONO_NATIVE_ASANY:
-       case MONO_NATIVE_VARIANTBOOL:
-       case MONO_NATIVE_FUNC:
-       case MONO_NATIVE_LPSTRUCT:
-               *align =  4;
-               return sizeof (gpointer);
-       case MONO_NATIVE_STRUCT: 
-               klass = mono_class_from_mono_type (type);
-               return mono_class_native_size (klass, align);
-       case MONO_NATIVE_BYVALTSTR: {
-               int esize = unicode ? 2: 1;
-               g_assert (mspec);
-               *align = esize;
-               return mspec->num_elem * esize;
-       }
-       case MONO_NATIVE_BYVALARRAY: {
-               int esize;
-               klass = mono_class_from_mono_type (type);
-               esize = mono_class_native_size (klass->element_class, align);
-               g_assert (mspec);
-               return mspec->num_elem * esize;
-       }
-       case MONO_NATIVE_CURRENCY:
-       case MONO_NATIVE_VBBYREFSTR:
-       case MONO_NATIVE_CUSTOM:
-       default:
-               g_error ("native type %02x not implemented", native_type); 
-               break;
-       }
-       g_assert_not_reached ();
-       return 0;
-}
-
 const char*
 mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
 {
@@ -3023,7 +3231,7 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
 
        loc.t = tdef;
        loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
-       loc.idx = ((idx + 1) << HAS_FIELD_MARSHAL_BITS) | (is_field? HAS_FIELD_MARSHAL_FIELDSREF: HAS_FIELD_MARSHAL_PARAMDEF);
+       loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
 
        if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return NULL;
@@ -3034,11 +3242,11 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
 static MonoMethod*
 method_from_method_def_or_ref (MonoImage *m, guint32 tok)
 {
-       guint32 idx = tok >> METHODDEFORREF_BITS;
-       switch (tok & METHODDEFORREF_MASK) {
-       case METHODDEFORREF_METHODDEF:
+       guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
+       switch (tok & MONO_METHODDEFORREF_MASK) {
+       case MONO_METHODDEFORREF_METHODDEF:
                return mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
-       case METHODDEFORREF_METHODREF:
+       case MONO_METHODDEFORREF_METHODREF:
                return mono_get_method (m, MONO_TOKEN_MEMBER_REF | idx, NULL);
        }
        g_assert_not_reached ();
@@ -3098,3 +3306,204 @@ mono_class_get_overrides (MonoImage *image, guint32 type_token, gint32 *num_over
        return result;
 }
 
+/**
+ * mono_guid_to_string:
+ *
+ * Converts a 16 byte Microsoft GUID to the standard string representation.
+ */
+char *
+mono_guid_to_string (const guint8 *guid)
+{
+       return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", 
+                               guid[3], guid[2], guid[1], guid[0],
+                               guid[5], guid[4],
+                               guid[7], guid[6],
+                               guid[8], guid[9],
+                               guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
+}
+
+static MonoClass**
+get_constraints (MonoImage *image, int owner)
+{
+       MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
+       guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
+       guint32 i, token, found;
+       MonoClass *klass, **res;
+       GList *cons = NULL, *tmp;
+       
+
+       found = 0;
+       for (i = 0; i < tdef->rows; ++i) {
+               mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
+               if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
+                       token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
+                       klass = mono_class_get (image, token);
+                       cons = g_list_append (cons, klass);
+                       ++found;
+               } else {
+                       /* contiguous list finished */
+                       if (found)
+                               break;
+               }
+       }
+       if (!found)
+               return NULL;
+       res = g_new0 (MonoClass*, found + 1);
+       for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
+               res [i] = tmp->data;
+       }
+       g_list_free (cons);
+       return res;
+}
+
+MonoGenericParam *
+mono_metadata_load_generic_params (MonoImage *image, guint32 token, guint32 *num)
+{
+       MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
+       guint32 cols [MONO_GENERICPARAM_SIZE];
+       guint32 i, owner, last_num, n;
+       MonoGenericParam *params;
+
+       if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
+               owner = MONO_TYPEORMETHOD_TYPE;
+       else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
+               owner = MONO_TYPEORMETHOD_METHOD;
+       else {
+               g_error ("wrong token %x to load_generics_params", token);
+       }
+       owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
+       if (num)
+               *num = 0;
+       if (!tdef->base)
+               return NULL;
+
+       for (i = 0; i < tdef->rows; ++i) {
+               mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE);
+               if (cols [MONO_GENERICPARAM_OWNER] == owner)
+                       break;
+       }
+       last_num = 0;
+       if (i >= tdef->rows)
+               return NULL;
+       params = NULL;
+       n = 0;
+       do {
+               n++;
+               params = g_realloc (params, sizeof (MonoGenericParam) * n);
+               params [n - 1].pklass = NULL;
+               params [n - 1].method = 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 = get_constraints (image, i + 1);
+               if (++i >= tdef->rows)
+                       break;
+               mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE);
+       } while (cols [MONO_GENERICPARAM_OWNER] == owner);
+       
+       if (num)
+               *num = n;
+       return params;
+}
+
+gboolean
+mono_type_is_byref (MonoType *type)
+{
+       return type->byref;
+}
+
+int
+mono_type_get_type (MonoType *type)
+{
+       return type->type;
+}
+
+/* For MONO_TYPE_FNPTR */
+MonoMethodSignature*
+mono_type_get_signature (MonoType *type)
+{
+       return type->data.method;
+}
+
+/* For MONO_TYPE_CLASS, VALUETYPE */
+MonoClass*
+mono_type_get_class (MonoType *type)
+{
+       return type->data.klass;
+}
+
+/* For MONO_TYPE_ARRAY */
+MonoArrayType*
+mono_type_get_array_type (MonoType *type)
+{
+       return type->data.array;
+}
+
+MonoClass*
+mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
+{
+       /* FIXME: implement */
+       return NULL;
+}
+
+MonoType*
+mono_signature_get_return_type (MonoMethodSignature *sig)
+{
+       return sig->ret;
+}
+
+MonoType*
+mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
+{
+       MonoType** type;
+       if (!iter)
+               return NULL;
+       if (!*iter) {
+               /* start from the first */
+               if (sig->param_count) {
+                       *iter = &sig->params [0];
+                       return sig->params [0];
+               } else {
+                       /* no method */
+                       return NULL;
+               }
+       }
+       type = *iter;
+       type++;
+       if (type < &sig->params [sig->param_count]) {
+               *iter = type;
+               return *type;
+       }
+       return NULL;
+}
+
+guint32
+mono_signature_get_param_count (MonoMethodSignature *sig)
+{
+       return sig->param_count;
+}
+
+guint32
+mono_signature_get_call_conv (MonoMethodSignature *sig)
+{
+       return sig->call_convention;
+}
+
+int
+mono_signature_vararg_start (MonoMethodSignature *sig)
+{
+       return sig->sentinelpos;
+}
+
+gboolean
+mono_signature_is_instance (MonoMethodSignature *sig)
+{
+       return sig->hasthis;
+}
+
+gboolean
+mono_signature_explicit_this (MonoMethodSignature *sig)
+{
+       return sig->explicit_this;
+}
+