Sat Jan 8 19:03:26 CET 2005 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / reflection.c
index 24e54c982e3a5ef9202a5d03a86ade74511475ff..6f2ed9414154c65f78769320161a773c299c1440 100644 (file)
@@ -220,7 +220,6 @@ string_heap_init (MonoDynamicStream *sh)
        string_heap_insert (sh, "");
 }
 
-#if 0 /* never used */
 static void
 string_heap_free (MonoDynamicStream *sh)
 {
@@ -228,7 +227,6 @@ string_heap_free (MonoDynamicStream *sh)
        g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
        g_hash_table_destroy (sh->hash);
 }
-#endif
 
 static guint32
 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
@@ -308,13 +306,13 @@ add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int
        copy = g_malloc (s1+s2);
        memcpy (copy, b1, s1);
        memcpy (copy + s1, b2, s2);
-       if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
+       if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
                g_free (copy);
                idx = GPOINTER_TO_UINT (oldval);
        } else {
                idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
                mono_image_add_stream_data (&assembly->blob, b2, s2);
-               mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
+               g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
        }
        return idx;
 }
@@ -464,10 +462,10 @@ encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char
        }
 
        mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
-       encode_type (assembly, gclass->generic_type, p, &p);
-       mono_metadata_encode_value (gclass->type_argc, p, &p);
-       for (i = 0; i < gclass->type_argc; ++i)
-               encode_type (assembly, gclass->type_argv [i], p, &p);
+       encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
+       mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
+       for (i = 0; i < gclass->inst->type_argc; ++i)
+               encode_type (assembly, gclass->inst->type_argv [i], p, &p);
 
        *endbuf = p;
 }
@@ -595,10 +593,10 @@ generic_class_get_signature_size (MonoGenericClass *gclass)
                g_assert_not_reached ();
        }
 
-       size += 1 + type_get_signature_size (gclass->generic_type);
+       size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
        size += 4;
-       for (i = 0; i < gclass->type_argc; ++i)
-               size += type_get_signature_size (gclass->type_argv [i]);
+       for (i = 0; i < gclass->inst->type_argc; ++i)
+               size += type_get_signature_size (gclass->inst->type_argv [i]);
 
        return size;
 }
@@ -1219,7 +1217,7 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly
        /* room in this table is already allocated */
        table = &assembly->tables [MONO_TABLE_METHOD];
        *mb->table_idx = table->next_idx ++;
-       mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
+       g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
        values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
        name = mono_string_to_utf8 (mb->name);
        values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
@@ -1315,9 +1313,9 @@ reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, Mono
        rmb->refs = NULL;
 
        if (mb->dll) {
-               rmb->charset = rmb->charset & 0xf;
-               rmb->lasterr = rmb->charset & 0x40;
-               rmb->native_cc = rmb->native_cc;
+               rmb->charset = mb->charset & 0xf;
+               rmb->lasterr = mb->charset & 0x40;
+               rmb->native_cc = mb->native_cc;
                rmb->dllentry = mb->dllentry;
                rmb->dll = mb->dll;
        }
@@ -1744,7 +1742,7 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *ass
                fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
        table = &assembly->tables [MONO_TABLE_FIELD];
        fb->table_idx = table->next_idx ++;
-       mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
+       g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
        values = table->values + fb->table_idx * MONO_FIELD_SIZE;
        name = mono_string_to_utf8 (fb->name);
        values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
@@ -1823,7 +1821,7 @@ property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBui
                        MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
                        encode_reflection_type (assembly, pt, p, &p);
                }
-       } else {
+       } else if (smb) {
                /* the property type is the last param */
                encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
                for (i = 0; i < nparams; ++i) {
@@ -1831,6 +1829,10 @@ property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBui
                        encode_reflection_type (assembly, pt, p, &p);
                }
        }
+       else {
+               encode_reflection_type (assembly, fb->type, p, &p);
+       }
+
        /* store length */
        g_assert (p - buf < size);
        mono_metadata_encode_value (p-buf, b, &b);
@@ -2426,7 +2428,7 @@ encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmetho
        char *buf;
        char *p;
        int i;
-       guint32 nparams =  gmethod->mtype_argc;
+       guint32 nparams =  gmethod->inst->type_argc;
        guint32 size = 10 + nparams * 10;
        guint32 idx;
        char blob_size [6];
@@ -2443,7 +2445,7 @@ encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmetho
        mono_metadata_encode_value (nparams, p, &p);
 
        for (i = 0; i < nparams; i++)
-               encode_type (assembly, gmethod->mtype_argv [i], p, &p);
+               encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
 
        /* store length */
        g_assert (p - buf < size);
@@ -2464,7 +2466,8 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
 
        table = &assembly->tables [MONO_TABLE_METHODSPEC];
 
-       g_assert (method->signature->is_inflated);
+       g_assert (method->is_inflated);
+       method = mono_get_inflated_method (method);
        imethod = (MonoMethodInflated *) method;
        declaring = imethod->declaring;
 
@@ -2510,7 +2513,8 @@ mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
        if (token)
                return token;
 
-       g_assert (m->signature->is_inflated);
+       g_assert (m->is_inflated);
+       m = mono_get_inflated_method (m);
        imethod = (MonoMethodInflated *) m;
 
        if (imethod->declaring->signature->generic_param_count) {
@@ -3188,6 +3192,14 @@ mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModu
                        (p) += 4 - (__diff & 3);\
        } while (0)
 
+static int
+compare_constants (const void *a, const void *b)
+{
+       const guint32 *a_values = a;
+       const guint32 *b_values = b;
+       return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
+}
+
 static int
 compare_semantics (const void *a, const void *b)
 {
@@ -3232,7 +3244,12 @@ compare_genericparam (const void *a, const void *b)
        const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
        const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
 
-       return (*b_entry)->owner - (*a_entry)->owner;
+       if ((*b_entry)->owner == (*a_entry)->owner)
+               return 
+                       (*a_entry)->gparam->type.type->data.generic_param->num - 
+                       (*b_entry)->gparam->type.type->data.generic_param->num;
+       else
+               return (*a_entry)->owner - (*b_entry)->owner;
 }
 
 static int
@@ -3426,6 +3443,9 @@ build_compressed_metadata (MonoDynamicImage *assembly)
        p = (unsigned char*)int32val;
 
        /* sort the tables that still need sorting */
+       table = &assembly->tables [MONO_TABLE_CONSTANT];
+       if (table->rows)
+               qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
        table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
        if (table->rows)
                qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
@@ -3518,7 +3538,7 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
                                idx = field->table_idx;
                        } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
                                MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
-                               idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
+                               idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
                        } else {
                                g_assert_not_reached ();
                        }
@@ -3533,7 +3553,7 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
                        } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
                                           !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
                                MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
-                               idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
+                               idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
                        } else {
                                g_assert_not_reached ();
                        }
@@ -3549,9 +3569,11 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
                                am = (MonoReflectionArrayMethod*)iltoken->member;
                                idx = am->table_idx;
                        } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
-                                  !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
+                                  !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
+                                  !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
+                                  !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
                                MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
-                               g_assert (m->klass->generic_class);
+                               g_assert (m->klass->generic_class || m->klass->generic_container);
                                continue;
                        } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
                                continue;
@@ -3566,7 +3588,7 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
                        }
                        break;
                case MONO_TABLE_METHODSPEC:
-                       if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
+                       if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
                                MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
                                g_assert (m->signature->generic_param_count);
                                continue;
@@ -3611,7 +3633,7 @@ fixup_cattrs (MonoDynamicImage *assembly)
 
                        if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
                                MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
-                               idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
+                               idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
                                values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
                        }
                }
@@ -4113,9 +4135,11 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean c
                token = mono_metadata_token_from_dor (
                        mono_image_typedef_or_ref (assembly, tb->type));
        } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
-                       strcmp (klass->name, "MonoMethod") == 0) {
+                  strcmp (klass->name, "MonoMethod") == 0 ||
+                  strcmp (klass->name, "MonoGenericMethod") == 0 ||
+                  strcmp (klass->name, "MonoGenericCMethod") == 0) {
                MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
-               if (m->method->signature->is_inflated) {
+               if (m->method->is_inflated) {
                        if (create_methodspec)
                                token = mono_image_get_methodspec_token (assembly, m->method);
                        else
@@ -4210,14 +4234,14 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c
        mono_image_init (&image->image);
 
        image->token_fixups = mono_g_hash_table_new (NULL, NULL);
-       image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
-       image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
-       image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
+       image->method_to_table_idx = g_hash_table_new (NULL, NULL);
+       image->field_to_table_idx = g_hash_table_new (NULL, NULL);
+       image->method_aux_hash = g_hash_table_new (NULL, NULL);
        image->handleref = g_hash_table_new (NULL, NULL);
        image->tokens = mono_g_hash_table_new (NULL, NULL);
        image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
        image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
-       image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
+       image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
        image->gen_params = g_ptr_array_new ();
 
        string_heap_init (&image->sheap);
@@ -4274,6 +4298,7 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
 #endif
 
        assembly->assembly.dynamic = TRUE;
+       assembly->assembly.corlib_internal = assemblyb->corlib_internal;
        assemblyb->assembly.assembly = (MonoAssembly*)assembly;
        assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
        if (assemblyb->culture)
@@ -4789,7 +4814,7 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
                        MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
                        table_idx = methodb->table_idx;
                } else {
-                       table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
+                       table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
                }
                cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
        } else {
@@ -4905,7 +4930,10 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
        mono_dynamic_stream_reset (&assembly->us);
        mono_dynamic_stream_reset (&assembly->blob);
        mono_dynamic_stream_reset (&assembly->guid);
-       mono_dynamic_stream_reset (&assembly->sheap);
+       string_heap_free (&assembly->sheap);
+
+       g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
+       g_hash_table_destroy (assembly->blob_cache);
 }
 
 MonoReflectionModule *
@@ -5066,6 +5094,7 @@ mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
                        mono_defaults.corlib, "System.Reflection", "Assembly");
        res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
        res->assembly = assembly;
+
        CACHE_OBJECT (assembly, res, NULL);
        return res;
 }
@@ -5194,12 +5223,13 @@ mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
                return t1->data.array->eklass == t2->data.array->eklass;
        case MONO_TYPE_GENERICINST: {
                int i;
-               if (t1->data.generic_class->type_argc != t2->data.generic_class->type_argc)
+               if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
                        return FALSE;
-               if (!mono_metadata_type_equal (t1->data.generic_class->generic_type, t2->data.generic_class->generic_type))
+               if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
+                                              &t2->data.generic_class->container_class->byval_arg))
                        return FALSE;
-               for (i = 0; i < t1->data.generic_class->type_argc; ++i) {
-                       if (!mono_metadata_type_equal (t1->data.generic_class->type_argv [i], t2->data.generic_class->type_argv [i]))
+               for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
+                       if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
                                return FALSE;
                }
                return TRUE;
@@ -5250,7 +5280,7 @@ mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
        }
 
        gclass = geninst->data.generic_class;
-       gklass = mono_class_from_mono_type (gclass->generic_type);
+       gklass = gclass->container_class;
 
        mono_class_init (gclass->klass);
 
@@ -5260,7 +5290,7 @@ mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
        if (gklass->wastypebuilder && gklass->reflection_info)
                res->generic_type = gklass->reflection_info;
        else
-               res->generic_type = mono_type_get_object (domain, gclass->generic_type);
+               res->generic_type = mono_type_get_object (domain, &gclass->container_class->byval_arg);
 
        return res;
 }
@@ -5327,6 +5357,25 @@ mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refcl
        MonoClass *klass;
        MonoReflectionMethod *ret;
 
+       if (method->is_inflated) {
+               MonoReflectionGenericMethod *gret;
+
+               refclass = method->klass;
+               CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
+               if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
+                       cname = "MonoGenericCMethod";
+               else
+                       cname = "MonoGenericMethod";
+               klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
+
+               gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
+               gret->method.method = method;
+               gret->method.name = mono_string_new (domain, method->name);
+               gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
+               CACHE_OBJECT (method, gret, refclass);
+               return (MonoReflectionMethod *) gret;
+       }
+
        if (!refclass)
                refclass = method->klass;
 
@@ -5597,7 +5646,7 @@ get_default_param_value_blobs (MonoMethod *method, char **blobs)
        mono_class_init (klass);
 
        if (klass->image->dynamic) {
-               MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
+               MonoReflectionMethodAux *aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
                if (aux && aux->param_defaults)
                        memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
                return;
@@ -6114,7 +6163,7 @@ mono_reflection_get_token (MonoObject *obj)
        } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
                        strcmp (klass->name, "MonoMethod") == 0) {
                MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
-               if (m->method->signature->is_inflated) {
+               if (m->method->is_inflated) {
                        g_assert_not_reached ();
                } else if (m->method->signature->generic_param_count) {
                        g_assert_not_reached ();
@@ -6699,7 +6748,7 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
        MonoReflectionMethodAux *aux;
 
        if (method->klass->image->dynamic) {
-               aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
+               aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
                if (!aux || !aux->param_cattr)
                        return NULL;
                return aux->param_cattr [param];
@@ -6709,8 +6758,7 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
        method_index = find_method_index (method);
        ca = &image->tables [MONO_TABLE_METHOD];
 
-       if (method->klass->generic_class || method->klass->generic_container ||
-           method->signature->generic_param_count) {
+       if (method->klass->generic_class || method->signature->generic_param_count) {
                /* FIXME FIXME FIXME */
                return NULL;
        }
@@ -6778,6 +6826,9 @@ mono_reflection_get_custom_attrs (MonoObject *obj)
        } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
                MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
                cinfo = mono_custom_attrs_from_method (rmethod->method);
+       } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
+               MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
+               cinfo = mono_custom_attrs_from_method (method);
        } else if (strcmp ("ParameterInfo", klass->name) == 0) {
                MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
                MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
@@ -7034,10 +7085,18 @@ handle_type:
        }
        /* it may be a boxed value or a Type */
        case MONO_TYPE_OBJECT: {
-               MonoClass *klass = mono_object_class (arg);
+               MonoClass *klass;
                char *str;
                guint32 slen;
+
+               if (arg == NULL) {
+                       *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
+                       *p++ = 0xFF;
+                       break;
+               }
                
+               klass = mono_object_class (arg);
+
                if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
                        *p++ = 0x50;
                        goto handle_type;
@@ -7349,8 +7408,7 @@ mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
        tb->generic_container = g_new0 (MonoGenericContainer, 1);
        tb->generic_container->klass = klass;
 
-       tb->generic_container->context = g_new0 (MonoGenericContext, 1);
-       tb->generic_container->context->container = tb->generic_container;
+       tb->generic_container->context.container = tb->generic_container;
 }
 
 /*
@@ -7386,6 +7444,8 @@ mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
                klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
                g_assert (klass->generic_container->type_params [i].owner);
        }
+
+       klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
 }
 
 /*
@@ -7561,7 +7621,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
 
                if (klass->image->dynamic)
-                       mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
+                       g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
 
                return m;
        } else if (!m->klass->dummy && 
@@ -7710,7 +7770,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
        }
 
        if (klass->image->dynamic && method_aux)
-               mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
+               g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
 
        return m;
 }      
@@ -7803,9 +7863,11 @@ static MonoType*
 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
                                            MonoType *parent)
 {
-       MonoClass *klass, *gklass;
+       MonoClass *klass;
        MonoReflectionTypeBuilder *tb = NULL;
        MonoGenericClass *gclass, *cached;
+       MonoDynamicGenericClass *dgclass = NULL;
+       gboolean is_dynamic = FALSE;
        MonoDomain *domain;
        MonoType *geninst;
        int icount, i;
@@ -7819,48 +7881,81 @@ do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_a
 
        domain = mono_object_domain (type);
 
-       gclass = g_new0 (MonoGenericClass, 1);
+       if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
+               tb = (MonoReflectionTypeBuilder *) type;
+
+               icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
+               is_dynamic = TRUE;
+       } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
+               MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
+               MonoReflectionType *rgt = rgi->generic_type;
+
+               g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
+               tb = (MonoReflectionTypeBuilder *) rgt;
+
+               icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
+               is_dynamic = TRUE;
+       } else {
+               icount = klass->interface_count;
+       }
+
+       if (is_dynamic) {
+               dgclass = g_new0 (MonoDynamicGenericClass, 1);
+               gclass = &dgclass->generic_class;
+               gclass->is_dynamic = TRUE;
+       } else
+               gclass = g_new0 (MonoGenericClass, 1);
 
-       gclass->type_argc = type_argc;
-       gclass->type_argv = types;
+       gclass->inst = g_new0 (MonoGenericInst, 1);
 
-       for (i = 0; i < gclass->type_argc; ++i) {
-               if (!gclass->is_open)
-                       gclass->is_open = mono_class_is_open_constructed_type (types [i]);
+       gclass->inst->type_argc = type_argc;
+       gclass->inst->type_argv = types;
+
+       for (i = 0; i < gclass->inst->type_argc; ++i) {
+               if (!gclass->inst->is_open)
+                       gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
        }
 
-       gclass->generic_type = &klass->byval_arg;
+       gclass->container_class = klass;
 
        if (klass->generic_class) {
                MonoGenericClass *kgclass = klass->generic_class;
                MonoGenericClass *ogclass = gclass;
 
                ogclass->context = g_new0 (MonoGenericContext, 1);
+               ogclass->context->container = ogclass->container_class->generic_container;
                ogclass->context->gclass = ogclass;
 
-               gclass = g_new0 (MonoGenericClass, 1);
+               if (is_dynamic) {
+                       dgclass = g_new0 (MonoDynamicGenericClass, 1);
+                       gclass = &dgclass->generic_class;
+                       gclass->is_dynamic = TRUE;
+               } else
+                       gclass = g_new0 (MonoGenericClass, 1);
+
+               gclass->inst = g_new0 (MonoGenericInst, 1);
 
-               gclass->type_argc = kgclass->type_argc;
-               gclass->type_argv = g_new0 (MonoType *, gclass->type_argc);
+               gclass->inst->type_argc = kgclass->inst->type_argc;
+               gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
 
-               for (i = 0; i < gclass->type_argc; i++) {
-                       MonoType *t = kgclass->type_argv [i];
+               for (i = 0; i < gclass->inst->type_argc; i++) {
+                       MonoType *t = kgclass->inst->type_argv [i];
 
                        t = mono_class_inflate_generic_type (t, ogclass->context);
 
-                       if (!gclass->is_open)
-                               gclass->is_open = mono_class_is_open_constructed_type (t);
+                       if (!gclass->inst->is_open)
+                               gclass->inst->is_open = mono_class_is_open_constructed_type (t);
 
-                       gclass->type_argv [i] = t;
+                       gclass->inst->type_argv [i] = t;
                }
 
-               gclass->generic_type = kgclass->generic_type;
+               gclass->container_class = kgclass->container_class;
        }
 
        geninst = g_new0 (MonoType, 1);
        geninst->type = MONO_TYPE_GENERICINST;
 
-       cached = g_hash_table_lookup (klass->image->generic_class_cache, gclass);
+       cached = mono_metadata_lookup_generic_class (gclass);
        if (cached) {
                g_free (gclass);
                mono_loader_unlock ();
@@ -7868,34 +7963,14 @@ do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_a
                return geninst;
        }
 
-       gklass = mono_class_from_mono_type (gclass->generic_type);
-       g_assert ((gclass->container = gklass->generic_container) != NULL);
-
        geninst->data.generic_class = gclass;
 
        gclass->parent = parent;
 
        gclass->context = g_new0 (MonoGenericContext, 1);
+       gclass->context->container = gclass->container_class->generic_container;
        gclass->context->gclass = gclass;
 
-       if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
-               tb = (MonoReflectionTypeBuilder *) type;
-
-               icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
-               gclass->is_dynamic = TRUE;
-       } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
-               MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
-               MonoReflectionType *rgt = rgi->generic_type;
-
-               g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
-               tb = (MonoReflectionTypeBuilder *) rgt;
-
-               icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
-               gclass->is_dynamic = TRUE;
-       } else {
-               icount = klass->interface_count;
-       }
-
        gclass->ifaces = g_new0 (MonoType *, icount);
        gclass->count_ifaces = icount;
 
@@ -7914,8 +7989,6 @@ do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_a
        mono_class_create_generic (gclass);
        mono_class_create_generic_2 (gclass);
 
-       g_hash_table_insert (klass->image->generic_class_cache, gclass, gclass);
-
        mono_loader_unlock ();
 
        return geninst;
@@ -7963,6 +8036,17 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
        return geninst;
 }
 
+static MonoType*
+dup_type (const MonoType *original)
+{
+       MonoType *r = g_new0 (MonoType, 1);
+       *r = *original;
+       r->attrs = original->attrs;
+       r->byref = original->byref;
+       mono_stats.generics_metadata_size += sizeof (MonoType);
+       return r;
+}
+
 MonoReflectionMethod*
 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
 {
@@ -7971,6 +8055,7 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
        MonoGenericContainer *container;
        MonoGenericMethod *gmethod;
        MonoGenericContext *context;
+       MonoGenericInst *ginst;
        int count, i;
 
        MONO_ARCH_SAVE_REGS;
@@ -7996,19 +8081,27 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
 
        if (!container->method_hash)
                container->method_hash = g_hash_table_new (
-                       mono_metadata_generic_method_hash, mono_metadata_generic_method_equal);
+                       (GHashFunc) mono_metadata_generic_method_hash,
+                       (GCompareFunc) mono_metadata_generic_method_equal);
 
-       gmethod = g_new0 (MonoGenericMethod, 1);
-       gmethod->mtype_argc = count;
-       gmethod->mtype_argv = g_new0 (MonoType *, count);
+       ginst = g_new0 (MonoGenericInst,1 );
+       ginst->type_argc = count;
+       ginst->type_argv = g_new0 (MonoType *, count);
        for (i = 0; i < count; i++) {
                MonoReflectionType *garg = mono_array_get (types, gpointer, i);
-               gmethod->mtype_argv [i] = garg->type;
+               ginst->type_argv [i] = dup_type (garg->type);
+
+               if (!ginst->is_open)
+                       ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
        }
+       ginst = mono_metadata_lookup_generic_inst (ginst);
+
+       gmethod = g_new0 (MonoGenericMethod, 1);
+       gmethod->container = container;
+       gmethod->inst = ginst;
 
        inflated = g_hash_table_lookup (container->method_hash, gmethod);
        if (inflated) {
-               g_free (gmethod->mtype_argv);
                g_free (gmethod);
 
                return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
@@ -8017,6 +8110,7 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
        gmethod->reflection_info = rmethod;
 
        context = g_new0 (MonoGenericContext, 1);
+       context->container = container;
        context->gclass = method->klass->generic_class;
        context->gmethod = gmethod;
 
@@ -8037,20 +8131,22 @@ inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoO
        gclass = type->type.type->data.generic_class;
 
        gmethod = g_new0 (MonoGenericMethod, 1);
+       gmethod->inst = g_new0 (MonoGenericInst, 1);
        gmethod->reflection_info = obj;
 
-       gmethod->mtype_argc = method->signature->generic_param_count;
-       gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
+       gmethod->inst->type_argc = method->signature->generic_param_count;
+       gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
 
-       for (i = 0; i < gmethod->mtype_argc; i++) {
+       for (i = 0; i < gmethod->inst->type_argc; i++) {
                MonoMethodNormal *mn = (MonoMethodNormal *) method;
                MonoGenericParam *gparam = &mn->generic_container->type_params [i];
 
                g_assert (gparam->pklass);
-               gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
+               gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
        }
 
        context = g_new0 (MonoGenericContext, 1);
+       context->container = gclass->container_class->generic_container;
        context->gclass = gclass;
        context->gmethod = gmethod;
 
@@ -8097,9 +8193,10 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
        if (gclass->initialized)
                return;
 
-       dgclass = gclass->dynamic_info = g_new0 (MonoDynamicGenericClass, 1);
+       g_assert (gclass->is_dynamic);
+       dgclass = (MonoDynamicGenericClass *) gclass;
 
-       gklass = mono_class_from_mono_type (gclass->generic_type);
+       gklass = gclass->container_class;
        mono_class_init (gklass);
 
        if (gclass->parent)
@@ -8874,3 +8971,165 @@ mono_declsec_flags_from_assembly (MonoAssembly *assembly)
        idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
        return mono_declsec_get_flags (assembly->image, idx);
 }
+
+
+/*
+ * Fill actions for the specific index (which may either be an encoded class token or
+ * an encoded method token) from the metadata image.
+ * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
+ */
+static MonoBoolean
+fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions)
+{
+       MonoBoolean result = FALSE;
+       MonoTableInfo *t;
+       guint32 cols [MONO_DECL_SECURITY_SIZE];
+       int index = mono_metadata_declsec_from_index (image, token);
+       int i;
+
+       t  = &image->tables [MONO_TABLE_DECLSECURITY];
+       for (i = index; i < t->rows; i++) {
+               mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
+
+               if (cols [MONO_DECL_SECURITY_PARENT] != token)
+                       return result;
+
+               /* if present only replace (class) permissions with method permissions */
+               /* if empty accept either class or method permissions */
+               switch (cols [MONO_DECL_SECURITY_ACTION]) {
+               case SECURITY_ACTION_DEMAND:
+                       if (!actions->demand.blob) {
+                               const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
+                               actions->demand.blob = (char*) (blob + 2);
+                               actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
+                               result = TRUE;
+                       }
+                       break;
+               case SECURITY_ACTION_NONCASDEMAND:
+                       if (!actions->noncasdemand.blob) {
+                               const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
+                               actions->noncasdemand.blob = (char*) (blob + 2);
+                               actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
+                               result = TRUE;
+                       }
+                       break;
+               case SECURITY_ACTION_DEMANDCHOICE:
+                       if (!actions->demandchoice.blob) {
+                               const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
+                               actions->demandchoice.blob = (char*) (blob + 2);
+                               actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
+                               result = TRUE;
+                       }
+                       break;
+               }
+       }
+
+       return result;
+}
+
+/*
+ * Collect all actions (that requires to generate code in mini) assigned for
+ * the specified method.
+ * Note: Don't use the content of actions if the function return FALSE.
+ */
+MonoBoolean
+mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
+{
+       MonoImage *image = method->klass->image;
+       MonoBoolean result = FALSE;
+       guint32 flags;
+
+       /* quick exit if no declarative security is present in the metadata */
+       if (!image->tables [MONO_TABLE_DECLSECURITY].rows)
+               return FALSE;
+
+       memset (demands, 0, sizeof (MonoDeclSecurityActions));
+
+       /* First we look for method-level attributes */
+       if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
+               guint32 idx = find_method_index (method);
+               idx <<= MONO_HAS_DECL_SECURITY_BITS;
+               idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
+               result = fill_actions_from_index (image, idx, demands);
+       }
+
+       /* Next we fill holes with class-level attributes */
+       /* Here we use (or create) the class declarative cache to look for demands */
+       flags = mono_declsec_flags_from_class (method->klass);
+       if (flags & (MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | MONO_DECLSEC_FLAG_DEMAND_CHOICE)) {
+               guint32 idx = mono_metadata_token_index (method->klass->type_token);
+               idx <<= MONO_HAS_DECL_SECURITY_BITS;
+               idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
+               result |= fill_actions_from_index (image, idx, demands);
+       }
+
+       /* The boolean return value is used as a shortcut in case nothing needs to
+          be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
+       return result;
+}
+
+static MonoBoolean
+get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
+{
+       guint32 cols [MONO_DECL_SECURITY_SIZE];
+       MonoTableInfo *t;
+       int i;
+
+       int index = mono_metadata_declsec_from_index (image, token);
+       if (index == -1)
+               return FALSE;
+
+       t =  &image->tables [MONO_TABLE_DECLSECURITY];
+       for (i = index; i < t->rows; i++) {
+               mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
+
+               /* shortcut - index are ordered */
+               if (token != cols [MONO_DECL_SECURITY_PARENT])
+                       return FALSE;
+
+               if (cols [MONO_DECL_SECURITY_ACTION] == action) {
+                       const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
+                       entry->blob = (char*) (metadata + 2);
+                       entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+MonoBoolean
+mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
+{
+       if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
+               guint32 idx = find_method_index (method);
+               idx <<= MONO_HAS_DECL_SECURITY_BITS;
+               idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
+               return get_declsec_action (method->klass->image, idx, action, entry);
+       }
+       return FALSE;
+}
+
+MonoBoolean
+mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
+{
+       /* use cache */
+       guint32 flags = mono_declsec_flags_from_class (klass);
+       if (declsec_flags_map [action] & flags) {
+               guint32 idx = mono_metadata_token_index (klass->type_token);
+               idx <<= MONO_HAS_DECL_SECURITY_BITS;
+               idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
+               return get_declsec_action (klass->image, idx, action, entry);
+       }
+       return FALSE;
+}
+
+MonoBoolean
+mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
+{
+       guint32 idx = 1; /* there is only one assembly */
+       idx <<= MONO_HAS_DECL_SECURITY_BITS;
+       idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
+
+       return get_declsec_action (assembly->image, idx, action, entry);
+}