2004-12-29 Martin Baulig <martin@ximian.com>
[mono.git] / mono / metadata / metadata.c
index eb490026e1cc7cced59b3ad19095156553157f31..523bec047179b46f0e840cb2847a3fc09e0a45e5 100644 (file)
 #include "private.h"
 #include "class.h"
 
-static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *generic_container,
+static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
                                         const char *ptr, const char **rptr);
 
 static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
+static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
+static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
+                                                   gboolean signature_only);
 
 /*
  * Encoding of the "description" argument:
@@ -373,7 +376,7 @@ const static struct {
  * mono_meta_table_name:
  * @table: table index
  *
- * Returns the name for the @table index
+ * Returns: the name for the @table index
  */
 const char *
 mono_meta_table_name (int table)
@@ -747,7 +750,7 @@ mono_metadata_compute_table_bases (MonoImage *meta)
  * @table: table code.
  * @idx: index of element to retrieve from @table.
  *
- * Returns a pointer to the @idx element in the metadata table
+ * Returns: a pointer to the @idx element in the metadata table
  * whose code is @table.
  */
 const char *
@@ -764,7 +767,7 @@ mono_metadata_locate (MonoImage *meta, int table, int idx)
  * @meta: metadata context
  * @token: metadata token
  *
- * Returns a pointer to the data in the metadata represented by the
+ * Returns: a pointer to the data in the metadata represented by the
  * token #token.
  */
 const char *
@@ -777,7 +780,7 @@ mono_metadata_locate_token (MonoImage *meta, guint32 token)
  * mono_metadata_get_table:
  * @table: table to retrieve
  *
- * Returns the MonoMetaTable structure for table @table
+ * Returns: the MonoMetaTable structure for table @table
  */
 const MonoMetaTable *
 mono_metadata_get_table (MonoMetaTableEnum table)
@@ -1057,14 +1060,14 @@ mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *p
  * and dimensions.
  */
 MonoArrayType *
-mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *generic_container,
+mono_metadata_parse_array_full (MonoImage *m, MonoGenericContext *generic_context,
                                const char *ptr, const char **rptr)
 {
        int i;
        MonoArrayType *array = g_new0 (MonoArrayType, 1);
        MonoType *etype;
        
-       etype = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
        array->eklass = mono_class_from_mono_type (etype);
        array->rank = mono_metadata_decode_value (ptr, &ptr);
 
@@ -1114,7 +1117,7 @@ mono_metadata_free_array (MonoArrayType *array)
  * private static
  * private static literal
  */
-static MonoType
+static const MonoType
 builtin_types[] = {
        /* data, attrs, type,              nmods, byref, pinned */
        {{NULL}, 0,     MONO_TYPE_VOID,    0,     0,     0},
@@ -1156,6 +1159,9 @@ builtin_types[] = {
 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
 
 static GHashTable *type_cache = NULL;
+static GHashTable *generic_inst_cache = NULL;
+static GHashTable *generic_class_cache = NULL;
+static int next_generic_inst_id = 0;
 
 /*
  * MonoTypes with modifies are never cached, so we never check or use that field.
@@ -1179,6 +1185,45 @@ mono_type_equal (gconstpointer ka, gconstpointer kb)
        return 1;
 }
 
+static guint
+mono_generic_inst_hash (gconstpointer data)
+{
+       const MonoGenericInst *ginst = (const MonoGenericInst *) data;
+       return ginst->type_argc | (ginst->is_open << 8);
+}
+
+static gboolean
+mono_generic_inst_equal (gconstpointer ka, gconstpointer kb)
+{
+       const MonoGenericInst *a = (const MonoGenericInst *) ka;
+       const MonoGenericInst *b = (const MonoGenericInst *) kb;
+       int i;
+
+       if ((a->is_open != b->is_open) || (a->type_argc != b->type_argc))
+               return FALSE;
+       for (i = 0; i < a->type_argc; ++i) {
+               if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], FALSE))
+                       return FALSE;
+       }
+       return TRUE;
+}
+
+static guint
+mono_generic_class_hash (gconstpointer data)
+{
+       const MonoGenericClass *gclass = (const MonoGenericClass *) data;
+       return mono_metadata_type_hash (&gclass->container_class->byval_arg);
+}
+
+static gboolean
+mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
+{
+       const MonoGenericClass *a = (const MonoGenericClass *) ka;
+       const MonoGenericClass *b = (const MonoGenericClass *) kb;
+
+       return _mono_metadata_generic_class_equal (a, b, FALSE);
+}
+
 /**
  * mono_metadata_init:
  *
@@ -1190,12 +1235,14 @@ mono_metadata_init (void)
        int i;
 
        type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
+       generic_inst_cache = g_hash_table_new (mono_generic_inst_hash, mono_generic_inst_equal);
+       generic_class_cache = g_hash_table_new (mono_generic_class_hash, mono_generic_class_equal);
 
        for (i = 0; i < NBUILTIN_TYPES (); ++i)
-               g_hash_table_insert (type_cache, &builtin_types [i], &builtin_types [i]);
+               g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
 }
 
-/*
+/**
  * mono_metadata_parse_type:
  * @m: metadata context
  * @mode: king of type that may be found at @ptr
@@ -1218,7 +1265,7 @@ mono_metadata_init (void)
  * Returns: a #MonoType structure representing the decoded type.
  */
 MonoType*
-mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *generic_container, MonoParseTypeMode mode,
+mono_metadata_parse_type_full (MonoImage *m, MonoGenericContext *generic_context, MonoParseTypeMode mode,
                               short opt_attrs, const char *ptr, const char **rptr)
 {
        MonoType *type, *cached;
@@ -1298,7 +1345,7 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *generic_conta
        type->byref = byref;
        type->pinned = pinned ? 1 : 0;
 
-       do_mono_metadata_parse_type (type, m, generic_container, ptr, &ptr);
+       do_mono_metadata_parse_type (type, m, generic_context, ptr, &ptr);
 
        if (rptr)
                *rptr = ptr;
@@ -1344,7 +1391,7 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
  * Returns: a MonoMethodSignature describing the signature.
  */
 MonoMethodSignature *
-mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 token)
+mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContext *generic_context, guint32 token)
 {
        MonoTableInfo *tables = image->tables;
        guint32 idx = mono_metadata_token_index (token);
@@ -1361,7 +1408,7 @@ mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *gene
        ptr = mono_metadata_blob_heap (image, sig);
        mono_metadata_decode_blob_size (ptr, &ptr);
 
-       return mono_metadata_parse_method_signature_full (image, generic_container, FALSE, ptr, NULL); 
+       return mono_metadata_parse_method_signature_full (image, generic_context, FALSE, ptr, NULL); 
 }
 
 MonoMethodSignature *
@@ -1404,14 +1451,15 @@ mono_metadata_signature_dup (MonoMethodSignature *sig)
  * Returns: a MonoMethodSignature describing the signature.
  */
 MonoMethodSignature *
-mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *generic_container,
+mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContext *generic_context,
                                           int def, const char *ptr, const char **rptr)
 {
        MonoMethodSignature *method;
        int i, ret_attrs = 0, *pattrs = NULL;
        guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
        guint32 gen_param_count = 0;
-       MonoGenericContainer *container = NULL;
+       gboolean is_open = FALSE;
+       MonoGenericContext *context = NULL;
 
        if (*ptr & 0x10)
                gen_param_count = 1;
@@ -1450,13 +1498,18 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *g
        method->call_convention = call_convention;
        method->generic_param_count = gen_param_count;
 
-       if (gen_param_count && (!generic_container || !generic_container->is_method)) {
-               container = g_new0 (MonoGenericContainer, 1);
-               container->parent = generic_container;
+       if (gen_param_count)
+               method->has_type_parameters = 1;
+
+       if (gen_param_count && (!generic_context || !generic_context->container->is_method)) {
+               MonoGenericContainer *container = g_new0 (MonoGenericContainer, 1);
+
+               if (generic_context)
+                       container->parent = generic_context->container;
                container->is_signature = 1;
 
-               container->context = g_new0 (MonoGenericContext, 1);
-               container->context->container = container;
+               context = &container->context;
+               container->context.container = container;
 
                container->type_argc = gen_param_count;
                container->type_params = g_new0 (MonoGenericParam, gen_param_count);
@@ -1466,10 +1519,12 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *g
                        container->type_params [i].num = i;
                }
        } else
-               container = generic_container;
+               context = generic_context;
 
-       if (call_convention != 0xa)
-               method->ret = mono_metadata_parse_type_full (m, container, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
+       if (call_convention != 0xa) {
+               method->ret = mono_metadata_parse_type_full (m, context, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
+               is_open = mono_class_is_open_constructed_type (method->ret);
+       }
 
        if (method->param_count) {
                method->sentinelpos = -1;
@@ -1482,10 +1537,14 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *g
                                ptr++;
                        }
                        method->params [i] = mono_metadata_parse_type_full (
-                               m, container, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
+                               m, context, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
+                       if (!is_open)
+                               is_open = mono_class_is_open_constructed_type (method->params [i]);
                }
        }
 
+       method->has_type_parameters = is_open;
+
        if (def && (method->call_convention == MONO_CALL_VARARG))
                method->sentinelpos = method->param_count;
 
@@ -1522,28 +1581,112 @@ mono_metadata_free_method_signature (MonoMethodSignature *sig)
        g_free (sig);
 }
 
-static void
-do_mono_metadata_parse_generic_inst (MonoType *type, MonoImage *m, MonoGenericContainer *generic_container,
-                                    const char *ptr, const char **rptr)
+MonoGenericInst *
+mono_metadata_lookup_generic_inst (MonoGenericInst *ginst)
 {
-       MonoGenericInst *ginst = g_new0 (MonoGenericInst, 1);
        MonoGenericInst *cached;
+       int i;
+
+       cached = g_hash_table_lookup (generic_inst_cache, ginst);
+       if (cached) {
+               for (i = 0; i < ginst->type_argc; i++)
+                       mono_metadata_free_type (ginst->type_argv [i]);
+               g_free (ginst->type_argv);
+               g_free (ginst);
+               return cached;
+       }
+
+       ginst->id = ++next_generic_inst_id;
+       g_hash_table_insert (generic_inst_cache, ginst, ginst);
+
+       return ginst;
+}
+
+MonoGenericClass *
+mono_metadata_lookup_generic_class (MonoGenericClass *gclass)
+{
+       MonoGenericClass *cached;
+       int i;
+
+       cached = g_hash_table_lookup (generic_class_cache, gclass);
+       if (cached)
+               return cached;
+
+       g_hash_table_insert (generic_class_cache, gclass, gclass);
+       return NULL;
+}
+
+MonoGenericInst *
+mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context)
+{
+       MonoGenericInst *nginst, *cached;
+       int i;
+
+       nginst = g_new0 (MonoGenericInst, 1);
+       nginst->type_argc = ginst->type_argc;
+       nginst->type_argv = g_new0 (MonoType*, nginst->type_argc);
+
+       for (i = 0; i < nginst->type_argc; i++) {
+               MonoType *t = ginst->type_argv [i];
+
+               nginst->type_argv [i] = mono_class_inflate_generic_type (t, context);
+
+               if (!nginst->is_open)
+                       nginst->is_open = mono_class_is_open_constructed_type (nginst->type_argv [i]);
+       }
+
+       return mono_metadata_lookup_generic_inst (nginst);
+}
+
+MonoGenericInst *
+mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContext *generic_context,
+                                 int count, const char *ptr, const char **rptr)
+{
+       MonoGenericInst *ginst;
+       int i;
+
+       ginst = g_new0 (MonoGenericInst, 1);
+       ginst->type_argc = count;
+       ginst->type_argv = g_new0 (MonoType*, count);
+
+       for (i = 0; i < ginst->type_argc; i++) {
+               MonoType *t = mono_metadata_parse_type_full (m, generic_context, 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;
+
+       return mono_metadata_lookup_generic_inst (ginst);
+}
+
+static void
+do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
+                                     const char *ptr, const char **rptr)
+{
+       MonoGenericClass *gclass = g_new0 (MonoGenericClass, 1);
+       MonoGenericContainer *container;
+       MonoGenericClass *cached;
+       MonoGenericInst *ginst;
        MonoClass *gklass;
+       MonoType *gtype;
        int i, count;
 
-       type->data.generic_inst = ginst;
+       type->data.generic_class = gclass;
 
-       ginst->context = g_new0 (MonoGenericContext, 1);
-       ginst->context->ginst = ginst;
+       gclass->context = g_new0 (MonoGenericContext, 1);
+       gclass->context->gclass = gclass;
 
-       ginst->klass = g_new0 (MonoClass, 1);
+       gclass->klass = g_new0 (MonoClass, 1);
 
-       ginst->generic_type = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_TYPE, 0, ptr, &ptr);
-       ginst->type_argc = count = mono_metadata_decode_value (ptr, &ptr);
-       ginst->type_argv = g_new0 (MonoType*, count);
+       gtype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       gclass->container_class = gklass = mono_class_from_mono_type (gtype);
 
-       gklass = mono_class_from_mono_type (ginst->generic_type);
-       g_assert ((ginst->container = gklass->generic_container) != NULL);
+       g_assert ((gclass->context->container = gklass->generic_container) != NULL);
+       count = mono_metadata_decode_value (ptr, &ptr);
 
        /*
         * Create the klass before parsing the type arguments.
@@ -1551,18 +1694,13 @@ do_mono_metadata_parse_generic_inst (MonoType *type, MonoImage *m, MonoGenericCo
         * See mcs/tests/gen-23.cs for an example.
         */
 
-       ginst->init_pending = TRUE;
+       gclass->init_pending = TRUE;
 
-       mono_class_create_generic (ginst);
+       mono_class_create_generic (gclass);
 
-       for (i = 0; i < ginst->type_argc; i++) {
-               MonoType *t = mono_metadata_parse_type_full (m, generic_container, 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);
-       }
+       gclass->inst = mono_metadata_parse_generic_inst (m, generic_context, count, ptr, &ptr);
 
+       mono_class_create_generic_2 (gclass);
 
        if (rptr)
                *rptr = ptr;
@@ -1572,7 +1710,7 @@ do_mono_metadata_parse_generic_inst (MonoType *type, MonoImage *m, MonoGenericCo
         * 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
+        * It's important to return the same MonoGenericClass * for each particualar
         * instantiation of a generic type (ie "Stack<Int32>") to make static fields
         * work.
         *
@@ -1581,24 +1719,23 @@ do_mono_metadata_parse_generic_inst (MonoType *type, MonoImage *m, MonoGenericCo
         * type.
         */
 
-       cached = g_hash_table_lookup (m->generic_inst_cache, ginst);
+       cached = g_hash_table_lookup (generic_class_cache, gclass);
        if (cached) {
-               g_free (ginst->klass);
-               g_free (ginst->type_argv);
-               g_free (ginst);
+               g_free (gclass->klass);
+               g_free (gclass);
 
-               type->data.generic_inst = cached;
+               type->data.generic_class = cached;
                return;
        } else {
-               g_hash_table_insert (m->generic_inst_cache, ginst, ginst);
+               g_hash_table_insert (generic_class_cache, gclass, gclass);
 
                mono_stats.generic_instance_count++;
-               mono_stats.generics_metadata_size += sizeof (MonoGenericInst) +
+               mono_stats.generics_metadata_size += sizeof (MonoGenericClass) +
                        sizeof (MonoGenericContext) +
-                       ginst->type_argc * sizeof (MonoType);
+                       gclass->inst->type_argc * sizeof (MonoType);
        }
 
-       ginst->init_pending = FALSE;
+       gclass->init_pending = FALSE;
 }
 
 /* 
@@ -1608,15 +1745,24 @@ do_mono_metadata_parse_generic_inst (MonoType *type, MonoImage *m, MonoGenericCo
  * Internal routine to parse a generic type parameter.
  */
 static MonoGenericParam *
-mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
+mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContext *generic_context,
                                   gboolean is_mvar, const char *ptr, const char **rptr)
 {
+       MonoGenericContainer *generic_container;
        int index;
 
        index = mono_metadata_decode_value (ptr, &ptr);
        if (rptr)
                *rptr = ptr;
 
+       g_assert (generic_context);
+       if (generic_context->gmethod)
+               generic_container = generic_context->gmethod->container;
+       else if (generic_context->gclass)
+               generic_container = generic_context->gclass->container_class->generic_container;
+       else
+               generic_container = generic_context->container;
+
        if (!is_mvar) {
                g_assert (generic_container);
                if (generic_container->parent) {
@@ -1653,7 +1799,7 @@ mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_c
  * This extracts a Type as specified in Partition II (22.2.12) 
  */
 static void
-do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *generic_container,
+do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
                             const char *ptr, const char **rptr)
 {
        type->type = mono_metadata_decode_value (ptr, &ptr);
@@ -1686,31 +1832,31 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
                break;
        }
        case MONO_TYPE_SZARRAY: {
-               MonoType *etype = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+               MonoType *etype = mono_metadata_parse_type_full (m, generic_context, 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_full (m, generic_container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+               type->data.type = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
                break;
        case MONO_TYPE_FNPTR:
-               type->data.method = mono_metadata_parse_method_signature_full (m, generic_container, 0, ptr, &ptr);
+               type->data.method = mono_metadata_parse_method_signature_full (m, generic_context, 0, ptr, &ptr);
                break;
        case MONO_TYPE_ARRAY:
-               type->data.array = mono_metadata_parse_array_full (m, generic_container, ptr, &ptr);
+               type->data.array = mono_metadata_parse_array_full (m, generic_context, ptr, &ptr);
                break;
 
        case MONO_TYPE_MVAR:
-               type->data.generic_param = mono_metadata_parse_generic_param (m, generic_container, TRUE, ptr, &ptr);
+               type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, TRUE, ptr, &ptr);
                break;
 
        case MONO_TYPE_VAR:
-               type->data.generic_param = mono_metadata_parse_generic_param (m, generic_container, FALSE, ptr, &ptr);
+               type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, FALSE, ptr, &ptr);
                break;
 
        case MONO_TYPE_GENERICINST:
-               do_mono_metadata_parse_generic_inst (type, m, generic_container, ptr, &ptr);
+               do_mono_metadata_parse_generic_class (type, m, generic_context, ptr, &ptr);
                break;
                
        default:
@@ -1880,7 +2026,7 @@ parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr
  * Returns: a MonoMethodHeader.
  */
 MonoMethodHeader *
-mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *generic_container, const char *ptr)
+mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContext *generic_context, const char *ptr)
 {
        MonoMethodHeader *mh;
        unsigned char flags = *(const unsigned char *) ptr;
@@ -1963,7 +2109,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *generic_contain
                mh->num_locals = len;
                for (i = 0; i < len; ++i)
                        mh->locals [i] = mono_metadata_parse_type_full (
-                               m, generic_container, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
+                               m, generic_context, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
        } else {
                mh = g_new0 (MonoMethodHeader, 1);
        }
@@ -2157,14 +2303,33 @@ table_locator (const void *a, const void *b)
                return 1;
 }
 
-/*
+static int
+declsec_locator (const void *a, const void *b)
+{
+       locator_t *loc = (locator_t *) a;
+       const char *bb = (const char *) b;
+       guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
+       guint32 col;
+
+       col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
+
+       if (loc->idx == col) {
+               loc->result = table_index;
+               return 0;
+       }
+       if (loc->idx < col)
+               return -1;
+       else
+               return 1;
+}
+
+/**
  * mono_metadata_typedef_from_field:
  * @meta: metadata context
  * @index: FieldDef token
  *
- * Returns the 1-based index into the TypeDef table of the type that
- * declared the field described by @index.
- * Returns 0 if not found.
+ * Returns: the 1-based index into the TypeDef table of the type that
+ * declared the field described by @index, or 0 if not found.
  */
 guint32
 mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
@@ -2191,9 +2356,8 @@ mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
  * @meta: metadata context
  * @index: MethodDef token
  *
- * Returns the 1-based index into the TypeDef table of the type that
- * declared the method described by @index.
- * Returns 0 if not found.
+ * Returns: the 1-based index into the TypeDef table of the type that
+ * declared the method described by @index.  0 if not found.
  */
 guint32
 mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
@@ -2220,7 +2384,7 @@ mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
  * @meta: metadata context
  * @index: typedef token
  * 
- * Returns and array of interfaces that the @index typedef token implements.
+ * Returns: and array of interfaces that the @index typedef token implements.
  * The number of elemnts in the array is returned in @count.
  */
 MonoClass**
@@ -2311,8 +2475,7 @@ mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
  * 
  * Returns: the 1-based index into the TypeDef table of the first type
  * that is nested inside the type described by @index. The search starts at
- * @start_index.
- * Returns 0 if no such type is found.
+ * @start_index.  returns 0 if no such type is found.
  */
 guint32
 mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
@@ -2344,7 +2507,7 @@ mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_ind
  * @meta: metadata context
  * @index: token representing a type
  * 
- * Returns the info stored in the ClassLAyout table for the given typedef token
+ * Returns: the info stored in the ClassLAyout table for the given typedef token
  * into the @packing and @size pointers.
  * Returns 0 if the info is not found.
  */
@@ -2408,6 +2571,38 @@ mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
        return loc.result + 1;
 }
 
+/*
+ * mono_metadata_declsec_from_index:
+ * @meta: metadata context
+ * @index: token representing the parent
+ * 
+ * Returns: the 0-based index into the DeclarativeSecurity table of the first 
+ * attribute which belongs to the metadata object described by @index.
+ * Returns -1 if no such attribute is found.
+ */
+guint32
+mono_metadata_declsec_from_index (MonoImage *meta, guint32 index)
+{
+       MonoTableInfo *tdef = &meta->tables [MONO_TABLE_DECLSECURITY];
+       locator_t loc;
+
+       if (!tdef->base)
+               return -1;
+
+       loc.idx = index;
+       loc.col_idx = MONO_DECL_SECURITY_PARENT;
+       loc.t = tdef;
+
+       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
+               return -1;
+
+       /* Find the first entry by searching backwards */
+       while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_DECL_SECURITY_PARENT) == index))
+               loc.result --;
+
+       return loc.result;
+}
+
 #ifdef DEBUG
 static void
 mono_backtrace (int limit)
@@ -2504,17 +2699,15 @@ mono_type_size (MonoType *t, gint *align)
        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;
-
-               g_assert (!ginst->is_open && !ginst->klass->generic_container);
+               MonoGenericClass *gclass = t->data.generic_class;
 
-               if (MONO_TYPE_ISSTRUCT (ginst->generic_type)) {
-                       MonoClass *gklass = mono_class_from_mono_type (ginst->generic_type);
+               g_assert (!gclass->inst->is_open && !gclass->klass->generic_container);
 
-                       if (gklass->enumtype)
-                               return mono_type_size (gklass->enum_basetype, align);
+               if (gclass->container_class->valuetype) {
+                       if (gclass->container_class->enumtype)
+                               return mono_type_size (gclass->container_class->enum_basetype, align);
                        else
-                               return mono_class_value_size (ginst->klass, align);
+                               return mono_class_value_size (gclass->klass, align);
                } else {
                        *align = __alignof__(gpointer);
                        return sizeof (gpointer);
@@ -2603,17 +2796,15 @@ mono_type_stack_size (MonoType *t, gint *align)
                }
        }
        case MONO_TYPE_GENERICINST: {
-               MonoGenericInst *ginst = t->data.generic_inst;
+               MonoGenericClass *gclass = t->data.generic_class;
 
-               g_assert (!ginst->is_open && !ginst->klass->generic_container);
+               g_assert (!gclass->inst->is_open && !gclass->klass->generic_container);
 
-               if (MONO_TYPE_ISSTRUCT (ginst->generic_type)) {
-                       MonoClass *gklass = mono_class_from_mono_type (ginst->generic_type);
-
-                       if (gklass->enumtype)
-                               return mono_type_stack_size (gklass->enum_basetype, align);
+               if (gclass->container_class->valuetype) {
+                       if (gclass->container_class->enumtype)
+                               return mono_type_stack_size (gclass->container_class->enum_basetype, align);
                        else {
-                               guint32 size = mono_class_value_size (ginst->klass, align);
+                               guint32 size = mono_class_value_size (gclass->klass, align);
 
                                *align = *align + __alignof__(gpointer) - 1;
                                *align &= ~(__alignof__(gpointer) - 1);
@@ -2635,39 +2826,40 @@ mono_type_stack_size (MonoType *t, gint *align)
 }
 
 gboolean
-mono_metadata_generic_inst_is_valuetype (MonoGenericInst *ginst)
-{
-       return MONO_TYPE_ISSTRUCT (ginst->generic_type);
-}
-
-guint
-mono_metadata_generic_inst_hash (MonoGenericInst *ginst)
+mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
 {
-       return mono_metadata_type_hash (ginst->generic_type);
+       return gclass->container_class->valuetype;
 }
 
 static gboolean
-_mono_metadata_generic_inst_equal (MonoGenericInst *g1, MonoGenericInst *g2, gboolean signature_only)
+_mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
 {
        int i;
 
-       if (g1->type_argc != g2->type_argc)
+       if ((g1->inst->type_argc != g2->inst->type_argc) || (g1->is_dynamic != g2->is_dynamic))
                return FALSE;
-       if (!do_mono_metadata_type_equal (g1->generic_type, g2->generic_type, signature_only))
+       if (!mono_metadata_class_equal (g1->container_class, g2->container_class, signature_only))
                return FALSE;
-       for (i = 0; i < g1->type_argc; ++i) {
-               if (!do_mono_metadata_type_equal (g1->type_argv [i], g2->type_argv [i], signature_only))
+       for (i = 0; i < g1->inst->type_argc; ++i) {
+               if (!do_mono_metadata_type_equal (g1->inst->type_argv [i], g2->inst->type_argv [i], signature_only))
                        return FALSE;
        }
        return TRUE;
 }
 
+guint
+mono_metadata_generic_method_hash (MonoGenericMethod *gmethod)
+{
+       return gmethod->inst->id;
+}
+
 gboolean
-mono_metadata_generic_inst_equal (MonoGenericInst *g1, MonoGenericInst *g2)
+mono_metadata_generic_method_equal (MonoGenericMethod *g1, MonoGenericMethod *g2)
 {
-       return _mono_metadata_generic_inst_equal (g1, g2, FALSE);
+       return (g1->container == g2->container) && (g1->inst == g2->inst);
 }
 
+
 /*
  * mono_metadata_type_hash:
  * @t1: a type
@@ -2691,7 +2883,7 @@ mono_metadata_type_hash (MonoType *t1)
        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 << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
        }
        return hash;
 }
@@ -2721,8 +2913,8 @@ mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only
 {
        if (c1 == c2)
                return TRUE;
-       if (c1->generic_inst && c2->generic_inst)
-               return _mono_metadata_generic_inst_equal (c1->generic_inst, c2->generic_inst, signature_only);
+       if (c1->generic_class && c2->generic_class)
+               return _mono_metadata_generic_class_equal (c1->generic_class, c2->generic_class, signature_only);
        if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
                return mono_metadata_generic_param_equal (
                        c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, FALSE);
@@ -2778,8 +2970,8 @@ do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only
                        return FALSE;
                return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass, signature_only);
        case MONO_TYPE_GENERICINST:
-               return _mono_metadata_generic_inst_equal (
-                       t1->data.generic_inst, t2->data.generic_inst, signature_only);
+               return _mono_metadata_generic_class_equal (
+                       t1->data.generic_class, t2->data.generic_class, signature_only);
        case MONO_TYPE_VAR:
                return mono_metadata_generic_param_equal (
                        t1->data.generic_param, t2->data.generic_param, FALSE);
@@ -2800,7 +2992,7 @@ mono_metadata_type_equal (MonoType *t1, MonoType *t2)
        return do_mono_metadata_type_equal (t1, t2, FALSE);
 }
 
-/*
+/**
  * mono_metadata_signature_equal:
  * @sig1: a signature
  * @sig2: another signature
@@ -3196,7 +3388,7 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
  * token.
  */
 MonoType *
-mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 type_spec)
+mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContext *generic_context, guint32 type_spec)
 {
        guint32 idx = mono_metadata_token_index (type_spec);
        MonoTableInfo *t;
@@ -3227,7 +3419,7 @@ mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContainer *gen
                ptr++;
        }
 
-       do_mono_metadata_parse_type (type, image, generic_container, ptr, &ptr);
+       do_mono_metadata_parse_type (type, image, generic_context, ptr, &ptr);
 
        mono_loader_unlock ();
 
@@ -3594,12 +3786,13 @@ get_constraints (MonoImage *image, int owner, MonoGenericContext *context)
 }
 
 MonoGenericContainer *
-mono_metadata_load_generic_params (MonoImage *image, guint32 token)
+mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
 {
        MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
        guint32 cols [MONO_GENERICPARAM_SIZE];
        guint32 i, owner = 0, last_num, n;
        MonoGenericContainer *container;
+       MonoGenericClass *gclass;
        MonoGenericParam *params;
 
        if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
@@ -3619,7 +3812,7 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token)
                if (cols [MONO_GENERICPARAM_OWNER] == owner)
                        break;
        }
-       last_num = 0;
+       last_num = i;
        if (i >= tdef->rows)
                return NULL;
        params = NULL;
@@ -3641,12 +3834,15 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token)
 
        container->type_argc = n;
        container->type_params = params;
+       container->parent = parent_container;
+
+       if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
+               container->is_method = 1;
 
-       container->context = g_new0 (MonoGenericContext, 1);
-       container->context->container = container;
+       container->context.container = container;
 
        for (i = 0; i < n; i++)
-               params [i].constraints = get_constraints (image, i + 1, container->context);
+               params [i].constraints = get_constraints (image, last_num + i + 1, &container->context);
 
        return container;
 }