Fix typo.
[mono.git] / mono / metadata / reflection.c
index 13fe5006039cb75d859551691831921ff973f7cc..0fe23865ee7b9d581f1f6a0889bc8316dea5989a 100644 (file)
@@ -43,6 +43,7 @@ typedef struct {
        MonoReflectionType *rtype;
        MonoArray *parameters;
        MonoArray *generic_params;
+       MonoGenericContainer *generic_container;
        MonoArray *pinfo;
        MonoArray *opt_types;
        guint32 attrs;
@@ -122,21 +123,6 @@ const unsigned char table_sizes [64] = {
        0       /* 0x2D */
 };
 
-/**
- * These macros can be used to allocate long living atomic data so it won't be
- * tracked by the garbage collector. We use libgc because it's apparently faster
- * than g_malloc.
- */
-#ifdef HAVE_BOEHM_GC
-#define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
-#define FREE_ATOMIC(ptr)
-#define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
-#else
-#define ALLOC_ATOMIC(size) g_malloc (size)
-#define FREE_ATOMIC(ptr) g_free (ptr)
-#define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
-#endif
-
 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
@@ -169,27 +155,34 @@ alloc_table (MonoDynamicTable *table, guint nrows)
                                table->alloc_rows *= 2;
                }
 
-               if (table->values)
-                       table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
-               else
-                       table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
+               table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
        }
 }
 
 static void
 make_room_in_stream (MonoDynamicStream *stream, int size)
 {
+       if (size <= stream->alloc_size)
+               return;
+       
        while (stream->alloc_size <= size) {
                if (stream->alloc_size < 4096)
                        stream->alloc_size = 4096;
                else
                        stream->alloc_size *= 2;
        }
-       if (stream->data)
-               stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
-       else
-               stream->data = ALLOC_ATOMIC (stream->alloc_size);
-}      
+       
+       stream->data = g_realloc (stream->data, stream->alloc_size);
+}
+
+static void
+mono_dynamic_stream_reset (MonoDynamicStream* stream)
+{
+       stream->alloc_size = stream->index = stream->offset = 0;
+       g_free (stream->data);
+       if (stream->hash)
+               g_hash_table_destroy (stream->hash);
+}
 
 static guint32
 string_heap_insert (MonoDynamicStream *sh, const char *str)
@@ -203,8 +196,8 @@ string_heap_insert (MonoDynamicStream *sh, const char *str)
 
        len = strlen (str) + 1;
        idx = sh->index;
-       if (idx + len > sh->alloc_size)
-               make_room_in_stream (sh, idx + len);
+       
+       make_room_in_stream (sh, idx + len);
 
        /*
         * We strdup the string even if we already copy them in sh->data
@@ -222,27 +215,25 @@ string_heap_init (MonoDynamicStream *sh)
 {
        sh->index = 0;
        sh->alloc_size = 4096;
-       sh->data = ALLOC_ATOMIC (4096);
+       sh->data = g_malloc (4096);
        sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
        string_heap_insert (sh, "");
 }
 
-#if 0 /* never used */
 static void
 string_heap_free (MonoDynamicStream *sh)
 {
-       FREE_ATOMIC (sh->data);
+       g_free (sh->data);
        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)
 {
        guint32 idx;
-       if (stream->alloc_size < stream->index + len)
-               make_room_in_stream (stream, stream->index + len);
+       
+       make_room_in_stream (stream, stream->index + len);
        memcpy (stream->data + stream->index, data, len);
        idx = stream->index;
        stream->index += len;
@@ -257,8 +248,8 @@ static guint32
 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
 {
        guint32 idx;
-       if (stream->alloc_size < stream->index + len)
-               make_room_in_stream (stream, stream->index + len);
+       
+       make_room_in_stream (stream, stream->index + len);
        memset (stream->data + stream->index, 0, len);
        idx = stream->index;
        stream->index += len;
@@ -312,11 +303,11 @@ add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int
        char *copy;
        gpointer oldkey, oldval;
        
-       copy = ALLOC_ATOMIC (s1+s2);
+       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)) {
-               FREE_ATOMIC (copy);
+               g_free (copy);
                idx = GPOINTER_TO_UINT (oldval);
        } else {
                idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
@@ -461,20 +452,20 @@ default_class_from_mono_type (MonoType *type)
 }
 
 static void
-encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
+encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
 {
        int i;
 
-       if (!ginst) {
+       if (!gclass) {
                g_assert_not_reached ();
                return;
        }
 
        mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
-       encode_type (assembly, ginst->generic_type, p, &p);
-       mono_metadata_encode_value (ginst->type_argc, p, &p);
-       for (i = 0; i < ginst->type_argc; ++i)
-               encode_type (assembly, ginst->type_argv [i], p, &p);
+       encode_type (assembly, gclass->generic_type, 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;
 }
@@ -539,7 +530,7 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
                mono_metadata_encode_value (0, p, &p);
                break;
        case MONO_TYPE_GENERICINST:
-               encode_generic_inst (assembly, type->data.generic_inst, p, &p);
+               encode_generic_class (assembly, type->data.generic_class, p, &p);
                break;
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
@@ -593,19 +584,19 @@ encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArra
 }
 
 static guint32
-generic_inst_get_signature_size (MonoGenericInst *ginst)
+generic_class_get_signature_size (MonoGenericClass *gclass)
 {
        guint32 size = 0;
        int i;
 
-       if (!ginst) {
+       if (!gclass) {
                g_assert_not_reached ();
        }
 
-       size += 1 + type_get_signature_size (ginst->generic_type);
+       size += 1 + type_get_signature_size (gclass->generic_type);
        size += 4;
-       for (i = 0; i < ginst->type_argc; ++i)
-               size += type_get_signature_size (ginst->type_argv [i]);
+       for (i = 0; i < gclass->inst->type_argc; ++i)
+               size += type_get_signature_size (gclass->inst->type_argv [i]);
 
        return size;
 }
@@ -652,7 +643,7 @@ type_get_signature_size (MonoType *type)
        case MONO_TYPE_ARRAY:
                return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
        case MONO_TYPE_GENERICINST:
-               return size + generic_inst_get_signature_size (type->data.generic_inst);
+               return size + generic_class_get_signature_size (type->data.generic_class);
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                return size + 5;
@@ -873,11 +864,11 @@ method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, g
                                clause->try_len = ex_info->len;
                        clause->handler_offset = ex_block->start;
                        clause->handler_len = ex_block->len;
-                       clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
-                               mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
                        if (ex_block->extype) {
-                               mono_g_hash_table_insert (assembly->tokens,
-                                         GUINT_TO_POINTER (clause->token_or_filter), ex_block->extype);
+                               clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
+                       } else {
+                               /* FIXME: handle filters */
+                               clause->data.filter_offset = 0;
                        }
                        finally_start = ex_block->start + ex_block->len;
 
@@ -981,7 +972,6 @@ fat_header:
        mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
        if (num_exception) {
                unsigned char sheader [4];
-               MonoExceptionClause clause;
                MonoILExceptionInfo * ex_info;
                MonoILExceptionBlock * ex_block;
                int j;
@@ -989,7 +979,7 @@ fat_header:
                stream_data_align (&assembly->code);
                /* always use fat format for now */
                sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
-               num_exception *= sizeof (MonoExceptionClause);
+               num_exception *= 6 * sizeof (guint32);
                num_exception += 4; /* include the size of the header */
                sheader [1] = num_exception & 0xff;
                sheader [2] = (num_exception >> 8) & 0xff;
@@ -1002,23 +992,37 @@ fat_header:
                        if (ex_info->handlers) {
                                int finally_start = ex_info->start + ex_info->len;
                                for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
+                                       guint32 val;
                                        ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
-                                       clause.flags = GUINT32_TO_LE (ex_block->type);
-                                       clause.try_offset = GUINT32_TO_LE (ex_info->start);
+                                       /* the flags */
+                                       val = GUINT32_TO_LE (ex_block->type);
+                                       mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+                                       /* try offset */
+                                       val = GUINT32_TO_LE (ex_info->start);
+                                       mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
                                        /* need fault, too, probably */
                                        if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
-                                               clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
+                                               val = GUINT32_TO_LE (finally_start - ex_info->start);
                                        else
-                                               clause.try_len = GUINT32_TO_LE (ex_info->len);
-                                       clause.handler_offset = GUINT32_TO_LE (ex_block->start);
-                                       clause.handler_len = GUINT32_TO_LE (ex_block->len);
+                                               val = GUINT32_TO_LE (ex_info->len);
+                                       mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+                                       /* handler offset */
+                                       val = GUINT32_TO_LE (ex_block->start);
+                                       mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+                                       /* handler len */
+                                       val = GUINT32_TO_LE (ex_block->len);
+                                       mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
                                        finally_start = ex_block->start + ex_block->len;
-                                       clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
-                                                       mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
-                                       clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
+                                       if (ex_block->extype) {
+                                               val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
+                                       } else {
+                                               /* FIXME: handle filters */
+                                               val = 0;
+                                       }
+                                       val = GUINT32_TO_LE (val);
+                                       mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
                                        /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
                                                        clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
-                                       mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
                                }
                        } else {
                                g_error ("No clauses for ex info block %d", i);
@@ -1288,6 +1292,7 @@ reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, Mono
        rmb->rtype = mb->rtype;
        rmb->parameters = mb->parameters;
        rmb->generic_params = mb->generic_params;
+       rmb->generic_container = mb->generic_container;
        rmb->opt_types = NULL;
        rmb->pinfo = mb->pinfo;
        rmb->attrs = mb->attrs;
@@ -1325,6 +1330,7 @@ reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoRe
        rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
        rmb->parameters = mb->parameters;
        rmb->generic_params = NULL;
+       rmb->generic_container = NULL;
        rmb->opt_types = NULL;
        rmb->pinfo = mb->pinfo;
        rmb->attrs = mb->attrs;
@@ -1352,6 +1358,7 @@ reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, Mono
        rmb->rtype = mb->rtype;
        rmb->parameters = mb->parameters;
        rmb->generic_params = NULL;
+       rmb->generic_container = NULL;
        rmb->opt_types = NULL;
        rmb->pinfo = NULL;
        rmb->attrs = mb->attrs;
@@ -2183,9 +2190,9 @@ create_typespec (MonoDynamicImage *assembly, MonoType *type)
        case MONO_TYPE_CLASS:
        case MONO_TYPE_VALUETYPE: {
                MonoClass *k = mono_class_from_mono_type (type);
-               if (!k || !k->generic_inst)
+               if (!k || !k->generic_class)
                        return 0;
-               encode_generic_inst (assembly, k->generic_inst, p, &p);
+               encode_generic_class (assembly, k->generic_class, p, &p);
                break;
        }
        default:
@@ -2417,7 +2424,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];
@@ -2434,7 +2441,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);
@@ -3223,7 +3230,12 @@ compare_genericparam (const void *a, const void *b)
        const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
        const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
 
-       return (*a_entry)->owner - (*b_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 (*b_entry)->owner - (*a_entry)->owner;
 }
 
 static int
@@ -3350,7 +3362,7 @@ build_compressed_metadata (MonoDynamicImage *assembly)
        int32val = (guint32*)p;
        *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
        p += 4;
-       memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
+       memcpy (p, meta->version, strlen (meta->version));
        p += GUINT32_FROM_LE (*int32val);
        align_pointer (meta->raw_metadata, p);
        int16val = (guint16*)p;
@@ -3403,7 +3415,7 @@ build_compressed_metadata (MonoDynamicImage *assembly)
        if (meta->idx_blob_wide)
                *p |= 0x04;
        ++p;
-       *p++ = 0; /* reserved */
+       *p++ = 1; /* reserved */
        int64val = (guint64*)p;
        *int64val++ = GUINT64_TO_LE (valid_mask);
        *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
@@ -3542,7 +3554,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;
-                               g_assert (m->klass->generic_inst);
+                               g_assert (m->klass->generic_class);
                                continue;
                        } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
                                continue;
@@ -4099,7 +4111,7 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean c
                MonoReflectionType *tb = (MonoReflectionType *)obj;
                token = mono_metadata_token_from_dor (
                        mono_image_typedef_or_ref (assembly, tb->type));
-       } else if (strcmp (klass->name, "MonoGenericInst") == 0) {
+       } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
                MonoReflectionType *tb = (MonoReflectionType *)obj;
                token = mono_metadata_token_from_dor (
                        mono_image_typedef_or_ref (assembly, tb->type));
@@ -4111,10 +4123,8 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean c
                                token = mono_image_get_methodspec_token (assembly, m->method);
                        else
                                token = mono_image_get_inflated_method_token (assembly, m->method);
-               } else if (m->method->signature->generic_param_count) {
-                       g_assert_not_reached ();
                } else if ((m->method->klass->image == &assembly->image) &&
-                        !m->method->klass->generic_inst) {
+                        !m->method->klass->generic_class) {
                        static guint32 method_table_idx = 0xffffff;
                        if (m->method->klass->wastypebuilder) {
                                /* we use the same token as the one that was assigned
@@ -4220,8 +4230,8 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c
        mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
        image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
        image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
-       mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
-       image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
+       image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
+       mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
        mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
        image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
        stream_data_align (&image->code);
@@ -4267,6 +4277,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)
@@ -4278,6 +4289,7 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
        assembly->save = assemblyb->access != 1;
 
        image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
+       image->initial_image = TRUE;
        assembly->assembly.aname.name = image->image.name;
        assembly->assembly.image = &image->image;
 
@@ -4538,6 +4550,14 @@ fixup_resource_directory (char *res_section, char *p, guint32 rva)
        }
 }
 
+static void
+checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
+{
+       guint32 dummy;
+       if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
+               g_error ("WriteFile returned %d\n", GetLastError ());
+}
+
 /*
  * mono_image_create_pefile:
  * @mb: a module builder object
@@ -4546,7 +4566,7 @@ fixup_resource_directory (char *res_section, char *p, guint32 rva)
  * assembly->pefile where it can be easily retrieved later in chunks.
  */
 void
-mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
+mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
        MonoMSDOSHeader *msdos;
        MonoDotNetHeader *header;
        MonoSectionTable *section;
@@ -4555,10 +4575,10 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
        guint32 header_start, section_start, file_offset, virtual_offset;
        MonoDynamicImage *assembly;
        MonoReflectionAssemblyBuilder *assemblyb;
-       MonoDynamicStream *pefile;
+       MonoDynamicStream pefile_stream = {0};
+       MonoDynamicStream *pefile = &pefile_stream;
        int i, nsections;
        guint32 *rva, value;
-       guint16 *data16;
        guchar *p;
        static const unsigned char msheader[] = {
                0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
@@ -4580,10 +4600,6 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
        assembly->machine = assemblyb->machine;
        ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
        ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
-
-       /* already created */
-       if (assembly->pefile.index)
-               return;
        
        mono_image_build_metadata (mb);
 
@@ -4605,9 +4621,7 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
                assembly_add_win32_resources (assembly, assemblyb);
 
        nsections = calc_section_size (assembly);
-
-       pefile = &assembly->pefile;
-
+       
        /* The DOS header and stub */
        g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
        mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
@@ -4641,7 +4655,6 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
 
        file_offset += FILE_ALIGN - 1;
        file_offset &= ~(FILE_ALIGN - 1);
-       mono_image_add_stream_zero (pefile, file_offset - pefile->index);
 
        image_size += section_start + sizeof (MonoSectionTable) * nsections;
 
@@ -4742,6 +4755,11 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
        header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
        header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
        header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
+       /* patch entrypoint name */
+       if (assemblyb->pekind == 1)
+               memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
+       else
+               memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
        /* patch imported function RVA name */
        rva = (guint32*)(assembly->code.data + assembly->iat_offset);
        *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
@@ -4751,14 +4769,14 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
        header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
        /* patch imported dll RVA name and other entries in the dir */
        rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
-       *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
+       *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
        rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
        *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
        rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
        *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
 
        p = (assembly->code.data + assembly->ilt_offset);
-       value = (assembly->text_rva + assembly->imp_names_offset - 2);
+       value = (assembly->text_rva + assembly->imp_names_offset);
        *p++ = (value) & 0xff;
        *p++ = (value >> 8) & (0xff);
        *p++ = (value >> 16) & (0xff);
@@ -4811,6 +4829,20 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
                section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
                section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
                section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
+               section ++;
+       }
+       
+       checked_write_file (file, pefile->data, pefile->index);
+       
+       mono_dynamic_stream_reset (pefile);
+       
+       for (i = 0; i < MONO_SECTION_MAX; ++i) {
+               if (!assembly->sections [i].size)
+                       continue;
+               
+               if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+                       g_error ("SetFilePointer returned %d\n", GetLastError ());
+               
                switch (i) {
                case MONO_SECTION_TEXT:
                        /* patch entry point */
@@ -4820,58 +4852,67 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
                        *p++ = (value >> 8) & 0xff;
                        *p++ = (value >> 16) & 0xff;
                        *p++ = (value >> 24) & 0xff;
-
-                       text_offset = assembly->sections [i].offset;
-                       memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
-                       text_offset += assembly->code.index;
-                       memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
-                       text_offset += assembly->resources.index;
-                       memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
-                       text_offset += assembly->meta_size;
-                       memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
+               
+                       checked_write_file (file, assembly->code.data, assembly->code.index);
+                       checked_write_file (file, assembly->resources.data, assembly->resources.index);
+                       checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
+                       checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
+                               
 
                        g_free (assembly->image.raw_metadata);
                        break;
-               case MONO_SECTION_RELOC:
-                       rva = (guint32*)(pefile->data + assembly->sections [i].offset);
-                       *rva = GUINT32_FROM_LE (assembly->text_rva);
-                       ++rva;
-                       *rva = GUINT32_FROM_LE (12);
-                       ++rva;
-                       data16 = (guint16*)rva;
+               case MONO_SECTION_RELOC: {
+                       struct {
+                               guint32 page_rva;
+                               guint32 block_size;
+                               guint16 type_and_offset;
+                               guint16 term;
+                       } reloc;
+                       
+                       g_assert (sizeof (reloc) == 12);
+                       
+                       reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
+                       reloc.block_size = GUINT32_FROM_LE (12);
+                       
                        /* 
                         * the entrypoint is always at the start of the text section 
                         * 3 is IMAGE_REL_BASED_HIGHLOW
                         * 2 is patch_size_rva - text_rva
                         */
-                       *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
-                       data16++;
-                       *data16 = 0; /* terminate */
+                       reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
+                       reloc.term = 0;
+                       
+                       checked_write_file (file, &reloc, sizeof (reloc));
+                       
                        break;
+               }
                case MONO_SECTION_RSRC:
                        if (assembly->win32_res) {
-                               text_offset = assembly->sections [i].offset;
 
                                /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
                                fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
-
-                               memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
+                               checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
                        }
                        break;
                default:
                        g_assert_not_reached ();
                }
-               section++;
        }
        
        /* check that the file is properly padded */
-#if 0
-       {
-               FILE *f = fopen ("mypetest.exe", "w");
-               fwrite (pefile->data, pefile->index, 1, f);
-               fclose (f);
-       }
-#endif
+       if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+               g_error ("SetFilePointer returned %d\n", GetLastError ());
+       if (! SetEndOfFile (file))
+               g_error ("SetEndOfFile returned %d\n", GetLastError ());
+       
+       mono_dynamic_stream_reset (&assembly->code);
+       mono_dynamic_stream_reset (&assembly->us);
+       mono_dynamic_stream_reset (&assembly->blob);
+       mono_dynamic_stream_reset (&assembly->guid);
+       string_heap_free (&assembly->sheap);
+
+       mono_g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
+       mono_g_hash_table_destroy (assembly->blob_cache);
 }
 
 MonoReflectionModule *
@@ -5032,6 +5073,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;
 }
@@ -5043,6 +5085,7 @@ mono_module_get_object   (MonoDomain *domain, MonoImage *image)
 {
        static MonoClass *System_Reflection_Module;
        MonoReflectionModule *res;
+       char* basename;
        
        CHECK_OBJECT (MonoReflectionModule *, image, NULL);
        if (!System_Reflection_Module)
@@ -5054,8 +5097,10 @@ mono_module_get_object   (MonoDomain *domain, MonoImage *image)
        res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
 
        res->fqname    = mono_string_new (domain, image->name);
-       res->name      = mono_string_new (domain, g_path_get_basename (image->name));
+       res->name      = mono_string_new (domain, basename = g_path_get_basename (image->name));
        res->scopename = mono_string_new (domain, image->module_name);
+       
+       g_free (basename);
 
        if (image->assembly->image == image) {
                res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
@@ -5157,12 +5202,12 @@ 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_inst->type_argc != t2->data.generic_inst->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_inst->generic_type, t2->data.generic_inst->generic_type))
+               if (!mono_metadata_type_equal (t1->data.generic_class->generic_type, t2->data.generic_class->generic_type))
                        return FALSE;
-               for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
-                       if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->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;
@@ -5198,32 +5243,32 @@ mymono_metadata_type_hash (MonoType *t1)
        return hash;
 }
 
-static MonoReflectionGenericInst*
-mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
+static MonoReflectionGenericClass*
+mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
 {
-       static MonoClass *System_Reflection_MonoGenericInst;
-       MonoReflectionGenericInst *res;
-       MonoGenericInst *ginst;
+       static MonoClass *System_Reflection_MonoGenericClass;
+       MonoReflectionGenericClass *res;
+       MonoGenericClass *gclass;
        MonoClass *gklass;
 
-       if (!System_Reflection_MonoGenericInst) {
-               System_Reflection_MonoGenericInst = mono_class_from_name (
-                       mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
-               g_assert (System_Reflection_MonoGenericInst);
+       if (!System_Reflection_MonoGenericClass) {
+               System_Reflection_MonoGenericClass = mono_class_from_name (
+                       mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
+               g_assert (System_Reflection_MonoGenericClass);
        }
 
-       ginst = geninst->data.generic_inst;
-       gklass = mono_class_from_mono_type (ginst->generic_type);
+       gclass = geninst->data.generic_class;
+       gklass = mono_class_from_mono_type (gclass->generic_type);
 
-       mono_class_init (ginst->klass);
+       mono_class_init (gclass->klass);
 
-       res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
+       res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
 
        res->type.type = geninst;
        if (gklass->wastypebuilder && gklass->reflection_info)
                res->generic_type = gklass->reflection_info;
        else
-               res->generic_type = mono_type_get_object (domain, ginst->generic_type);
+               res->generic_type = mono_type_get_object (domain, gclass->generic_type);
 
        return res;
 }
@@ -5249,8 +5294,8 @@ mono_type_get_object (MonoDomain *domain, MonoType *type)
                mono_domain_unlock (domain);
                return res;
        }
-       if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
-               res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
+       if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
+               res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
                mono_g_hash_table_insert (domain->type_hash, type, res);
                mono_domain_unlock (domain);
                return res;
@@ -5468,6 +5513,54 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
        return res;
 }
 
+/*
+ * mono_method_body_get_object:
+ * @domain: an app domain
+ * @method: a method
+ *
+ * Return an System.Reflection.MethodBody object representing the method @method.
+ */
+MonoReflectionMethodBody*
+mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
+{
+       static MonoClass *System_Reflection_MethodBody = NULL;
+       static MonoClass *System_Reflection_LocalVariableInfo = NULL;
+       MonoReflectionMethodBody *ret;
+       MonoMethodNormal *mn;
+       MonoMethodHeader *header;
+       int i;
+
+       if (!System_Reflection_MethodBody)
+               System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
+       if (!System_Reflection_LocalVariableInfo)
+               System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
+
+       CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
+
+       if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+           (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
+               return NULL;
+       mn = (MonoMethodNormal *)method;
+       header = mono_method_get_header (method);
+
+       ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
+       /* FIXME: Other fields */
+       ret->init_locals = header->init_locals;
+       ret->max_stack = header->max_stack;
+       ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
+       memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
+       ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
+       for (i = 0; i < header->num_locals; ++i) {
+               MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
+               info->local_type = mono_type_get_object (domain, header->locals [i]);
+               info->is_pinned = header->locals [i]->pinned;
+               info->local_index = 0;
+       }
+               
+       CACHE_OBJECT (method, ret, NULL);
+       return ret;
+}
+
 MonoObject *
 mono_get_dbnull_object (MonoDomain *domain)
 {
@@ -5505,7 +5598,7 @@ get_default_param_value_blobs (MonoMethod *method, char **blobs)
        if (!methodsig->param_count)
                return;
 
-       if (klass->generic_inst) {
+       if (klass->generic_class) {
                return; /* FIXME - ??? */
        }
 
@@ -5595,7 +5688,7 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
        while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
                p++;
        found_sep = 0;
-       while (*p == ' ' || *p == ',') {
+       while (g_ascii_isspace (*p) || *p == ',') {
                *p++ = 0;
                found_sep = 1;
                continue;
@@ -5653,7 +5746,7 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
                                p++;
                }
                found_sep = 0;
-               while (*p == ' ' || *p == ',') {
+               while (g_ascii_isspace (*p) || *p == ',') {
                        *p++ = 0;
                        found_sep = 1;
                        continue;
@@ -5674,8 +5767,10 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
  * extracted in the info structure.
  * the name param will be mangled, so, make a copy before passing it to this function.
  * The fields in info will be valid until the memory pointed to by name is valid.
- * Returns 0 on parse error.
+ *
  * See also mono_type_get_name () below.
+ *
+ * Returns: 0 on parse error.
  */
 int
 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
@@ -5774,7 +5869,7 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
                case ',':
                        *p++ = 0;
                        while (*p) {
-                               if (*p == ' ') {
+                               if (g_ascii_isspace (*p)) {
                                        ++p;
                                        continue;
                                }
@@ -5879,15 +5974,12 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
        if (!mono_domain_has_type_resolve (mono_domain_get ()))
                return NULL;
 
-       /* FIXME: Enabling this causes regressions (#65577) */
-       /*
        if (type_resolve) {
                if (*type_resolve) 
                        return NULL;
                else
                        *type_resolve = TRUE;
        }
-       */
        
        /* Reconstruct the type name */
        fullName = g_string_new ("");
@@ -5899,8 +5991,7 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
                g_string_append_printf (fullName, "+%s", (char*)mod->data);
 
        assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
-       if (assembly && (!image || (assembly->assembly->image == image))) {
-
+       if (assembly) {
                if (assembly->assembly->dynamic) {
                        /* Enumerate all modules */
                        MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
@@ -6035,7 +6126,7 @@ mono_reflection_get_token (MonoObject *obj)
                        g_assert_not_reached ();
                } else if (m->method->signature->generic_param_count) {
                        g_assert_not_reached ();
-               } else if (m->method->klass->generic_inst) {
+               } else if (m->method->klass->generic_class) {
                        g_assert_not_reached ();
                } else {
                        token = m->method->token;
@@ -6626,7 +6717,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_inst || method->klass->generic_container ||
+       if (method->klass->generic_class || method->klass->generic_container ||
            method->signature->generic_param_count) {
                /* FIXME FIXME FIXME */
                return NULL;
@@ -6705,6 +6796,9 @@ mono_reflection_get_custom_attrs (MonoObject *obj)
        } else if (strcmp ("TypeBuilder", klass->name) == 0) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
                cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
+       } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
+               MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
+               cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
        } else { /* handle other types here... */
                g_error ("get custom attrs not yet supported for %s", klass->name);
        }
@@ -6947,11 +7041,19 @@ handle_type:
                break;
        }
        /* it may be a boxed value or a Type */
-       case MONO_TYPE_OBJECT: {
-               MonoClass *klass = mono_object_class (arg);
+       case MONO_TYPE_OBJECT: {\r
+               MonoClass *klass;
                char *str;
                guint32 slen;
+\r
+               if (arg == NULL) {\r
+                       *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses\r
+                       *p++ = 0xFF;\r
+                       break;\r
+               }\r
                
+               klass = mono_object_class (arg);
+
                if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
                        *p++ = 0x50;
                        goto handle_type;
@@ -7247,13 +7349,35 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
  * mono_reflection_setup_generic_class:
  * @tb: a TypeBuilder object
  *
- * Setup the generic class after all generic parameters have been added.
+ * Setup the generic class before adding the first generic parameter.
  */
 void
 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
 {
        MonoClass *klass;
-       MonoGenericContainer *container;
+
+       MONO_ARCH_SAVE_REGS;
+
+       klass = my_mono_class_from_mono_type (tb->type.type);
+       if (tb->generic_container)
+               return;
+
+       tb->generic_container = g_new0 (MonoGenericContainer, 1);
+       tb->generic_container->klass = klass;
+
+       tb->generic_container->context.container = tb->generic_container;
+}
+
+/*
+ * mono_reflection_create_generic_class:
+ * @tb: a TypeBuilder object
+ *
+ * Creates the generic class after all generic parameters have been added.
+ */
+void
+mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
+{
+       MonoClass *klass;
        int count, i;
 
        MONO_ARCH_SAVE_REGS;
@@ -7265,14 +7389,17 @@ mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
        if (klass->generic_container || (count == 0))
                return;
 
-       klass->generic_container = container = g_new0 (MonoGenericContainer, 1);
+       g_assert (tb->generic_container && (tb->generic_container->klass == klass));
+
+       klass->generic_container = tb->generic_container;
 
-       container->type_argc = count;
-       container->type_params = g_new0 (MonoGenericParam, count);
+       klass->generic_container->type_argc = count;
+       klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
 
        for (i = 0; i < count; i++) {
                MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
-               container->type_params [i] = *gparam->type.type->data.generic_param;
+               klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
+               g_assert (klass->generic_container->type_params [i].owner);
        }
 }
 
@@ -7513,7 +7640,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                int count = mono_array_length (rmb->generic_params);
                MonoGenericContainer *container;
 
-               pm->generic_container = container = g_new0 (MonoGenericContainer, 1);
+               pm->generic_container = container = rmb->generic_container;
                container->type_argc = count;
                container->type_params = g_new0 (MonoGenericParam, count);
 
@@ -7688,17 +7815,18 @@ fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder*
 }
 
 static MonoType*
-do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
+do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
+                                           MonoType *parent)
 {
-       MonoClass *klass;
+       MonoClass *klass, *gklass;
        MonoReflectionTypeBuilder *tb = NULL;
-       MonoGenericInst *ginst, *cached;
+       MonoGenericClass *gclass, *cached;
        MonoDomain *domain;
        MonoType *geninst;
        int icount, i;
 
        klass = mono_class_from_mono_type (type->type);
-       if (!klass->generic_container && !klass->generic_inst &&
+       if (!klass->generic_container && !klass->generic_class &&
            !(klass->nested_in && klass->nested_in->generic_container))
                return NULL;
 
@@ -7706,75 +7834,89 @@ do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_a
 
        domain = mono_object_domain (type);
 
-       ginst = g_new0 (MonoGenericInst, 1);
+       gclass = g_new0 (MonoGenericClass, 1);
+       gclass->inst = g_new0 (MonoGenericInst, 1);
 
-       if (!klass->generic_inst) {
-               ginst->type_argc = type_argc;
-               ginst->type_argv = types;
+       gclass->inst->type_argc = type_argc;
+       gclass->inst->type_argv = types;
 
-               for (i = 0; i < ginst->type_argc; ++i) {
-                       if (!ginst->is_open)
-                               ginst->is_open = mono_class_is_open_constructed_type (types [i]);
-               }
+       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]);
+       }
 
-               ginst->generic_type = &klass->byval_arg;
-       } else {
-               MonoGenericInst *kginst = klass->generic_inst;
+       gclass->generic_type = &klass->byval_arg;
+
+       if (klass->generic_class) {
+               MonoGenericClass *kgclass = klass->generic_class;
+               MonoGenericClass *ogclass = gclass;
+
+               ogclass->context = g_new0 (MonoGenericContext, 1);
+               ogclass->context->container = ogclass->container;
+               ogclass->context->gclass = ogclass;
 
-               ginst->type_argc = kginst->type_argc;
-               ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
+               gclass = g_new0 (MonoGenericClass, 1);
+               gclass->inst = g_new0 (MonoGenericInst, 1);
 
-               for (i = 0; i < ginst->type_argc; i++) {
-                       MonoType *t = kginst->type_argv [i];
+               gclass->inst->type_argc = kgclass->inst->type_argc;
+               gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
 
-                       if (t->type == MONO_TYPE_VAR)
-                               t = types [t->data.generic_param->num];
+               for (i = 0; i < gclass->inst->type_argc; i++) {
+                       MonoType *t = kgclass->inst->type_argv [i];
 
-                       if (!ginst->is_open)
-                               ginst->is_open = mono_class_is_open_constructed_type (t);
+                       t = mono_class_inflate_generic_type (t, ogclass->context);
 
-                       ginst->type_argv [i] = t;
+                       if (!gclass->inst->is_open)
+                               gclass->inst->is_open = mono_class_is_open_constructed_type (t);
+
+                       gclass->inst->type_argv [i] = t;
                }
 
-               ginst->generic_type = kginst->generic_type;
+               gclass->generic_type = kgclass->generic_type;
        }
 
        geninst = g_new0 (MonoType, 1);
        geninst->type = MONO_TYPE_GENERICINST;
 
-       cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
+       cached = mono_metadata_lookup_generic_class (gclass);
        if (cached) {
-               g_free (ginst);
+               g_free (gclass);
                mono_loader_unlock ();
-               geninst->data.generic_inst = cached;
+               geninst->data.generic_class = cached;
                return geninst;
        }
 
-       geninst->data.generic_inst = ginst;
+       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;
 
-       ginst->context = g_new0 (MonoGenericContext, 1);
-       ginst->context->ginst = ginst;
+       gclass->context = g_new0 (MonoGenericContext, 1);
+       gclass->context->container = gclass->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;
-               ginst->is_dynamic = TRUE;
-       } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
-               MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
+               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;
-               ginst->is_dynamic = TRUE;
+               gclass->is_dynamic = TRUE;
        } else {
                icount = klass->interface_count;
        }
 
-       ginst->ifaces = g_new0 (MonoType *, icount);
-       ginst->count_ifaces = icount;
+       gclass->ifaces = g_new0 (MonoType *, icount);
+       gclass->count_ifaces = icount;
 
        for (i = 0; i < icount; i++) {
                MonoReflectionType *itype;
@@ -7783,14 +7925,13 @@ do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_a
                        itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
                else
                        itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
-               ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
-               if (!ginst->ifaces [i])
-                       ginst->ifaces [i] = itype->type;
+               gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
+               if (!gclass->ifaces [i])
+                       gclass->ifaces [i] = itype->type;
        }
 
-       mono_class_create_generic (ginst);
-
-       g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
+       mono_class_create_generic (gclass);
+       mono_class_create_generic_2 (gclass);
 
        mono_loader_unlock ();
 
@@ -7802,9 +7943,9 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
 {
        MonoClass *klass, *pklass = NULL;
        MonoReflectionType *parent = NULL;
-       MonoType *geninst;
+       MonoType *the_parent = NULL, *geninst;
        MonoReflectionTypeBuilder *tb = NULL;
-       MonoGenericInst *ginst;
+       MonoGenericClass *gclass;
        MonoDomain *domain;
 
        domain = mono_object_domain (type);
@@ -7821,27 +7962,44 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
                pklass = klass->parent;
                if (pklass)
                        parent = mono_type_get_object (domain, &pklass->byval_arg);
+               else if (klass->generic_class && klass->generic_class->parent) {
+                       parent = mono_type_get_object (domain, klass->generic_class->parent);
+                       pklass = mono_class_from_mono_type (klass->generic_class->parent);
+               }
        }
 
-       geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
+       if (pklass && pklass->generic_class)
+               the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
+
+       geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
        if (!geninst)
                return NULL;
 
-       ginst = geninst->data.generic_inst;
-
-       if (pklass && pklass->generic_inst)
-               ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
+       gclass = geninst->data.generic_class;
 
        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)
 {
        MonoMethod *method, *inflated;
        MonoReflectionMethodBuilder *mb = NULL;
+       MonoGenericContainer *container;
        MonoGenericMethod *gmethod;
        MonoGenericContext *context;
+       MonoGenericInst *ginst;
        int count, i;
 
        MONO_ARCH_SAVE_REGS;
@@ -7862,59 +8020,85 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
        if (count != mono_array_length (types))
                return NULL;
 
-       gmethod = g_new0 (MonoGenericMethod, 1);
-       gmethod->mtype_argc = count;
-       gmethod->mtype_argv = g_new0 (MonoType *, count);
+       container = ((MonoMethodNormal*) method)->generic_container;
+       g_assert (container);
+
+       if (!container->method_hash)
+               container->method_hash = g_hash_table_new (
+                       (GHashFunc) mono_metadata_generic_method_hash,
+                       (GCompareFunc) mono_metadata_generic_method_equal);
+
+       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);
+
+               return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
        }
 
        gmethod->reflection_info = rmethod;
 
        context = g_new0 (MonoGenericContext, 1);
-       context->ginst = method->klass->generic_inst;
+       context->container = container;
+       context->gclass = method->klass->generic_class;
        context->gmethod = gmethod;
 
        inflated = mono_class_inflate_generic_method (method, context, NULL);
+       g_hash_table_insert (container->method_hash, gmethod, inflated);
 
-       return mono_method_get_object (
-               mono_object_domain (rmethod), inflated, NULL);
+       return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
 }
 
 static MonoMethod *
-inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
+inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
 {
        MonoGenericMethod *gmethod;
-       MonoGenericInst *ginst;
+       MonoGenericClass *gclass;
        MonoGenericContext *context;
        int i;
 
-       ginst = type->type.type->data.generic_inst;
+       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->ginst = ginst;
+       context->container = gclass->container;
+       context->gclass = gclass;
        context->gmethod = gmethod;
 
-       return mono_class_inflate_generic_method (method, context, ginst->klass);
+       return mono_class_inflate_generic_method (method, context, gclass->klass);
 }
 
 static MonoMethod *
-inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
+inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
 {
        MonoMethod *method;
        MonoClass *klass;
@@ -7936,59 +8120,60 @@ inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
 }
 
 void
-mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods, 
-       MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
+mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
+                                         MonoArray *ctors, MonoArray *fields, MonoArray *properties,
+                                         MonoArray *events)
 {
-       MonoGenericInst *ginst;
-       MonoDynamicGenericInst *dginst;
+       MonoGenericClass *gclass;
+       MonoDynamicGenericClass *dgclass;
        MonoClass *klass, *gklass, *pklass;
        int i;
 
        MONO_ARCH_SAVE_REGS;
 
        klass = mono_class_from_mono_type (type->type.type);
-       ginst = type->type.type->data.generic_inst;
+       gclass = type->type.type->data.generic_class;
 
-       if (ginst->initialized)
+       if (gclass->initialized)
                return;
 
-       dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
+       dgclass = gclass->dynamic_info = g_new0 (MonoDynamicGenericClass, 1);
 
-       gklass = mono_class_from_mono_type (ginst->generic_type);
+       gklass = mono_class_from_mono_type (gclass->generic_type);
        mono_class_init (gklass);
 
-       if (ginst->parent)
-               pklass = mono_class_from_mono_type (ginst->parent);
+       if (gclass->parent)
+               pklass = mono_class_from_mono_type (gclass->parent);
        else
                pklass = gklass->parent;
 
        mono_class_setup_parent (klass, pklass);
 
-       dginst->count_methods = methods ? mono_array_length (methods) : 0;
-       dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
-       dginst->count_fields = fields ? mono_array_length (fields) : 0;
-       dginst->count_properties = properties ? mono_array_length (properties) : 0;
-       dginst->count_events = events ? mono_array_length (events) : 0;
+       dgclass->count_methods = methods ? mono_array_length (methods) : 0;
+       dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
+       dgclass->count_fields = fields ? mono_array_length (fields) : 0;
+       dgclass->count_properties = properties ? mono_array_length (properties) : 0;
+       dgclass->count_events = events ? mono_array_length (events) : 0;
 
-       dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
-       dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
-       dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
-       dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
-       dginst->events = g_new0 (MonoEvent, dginst->count_events);
+       dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
+       dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
+       dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
+       dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
+       dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
 
-       for (i = 0; i < dginst->count_methods; i++) {
+       for (i = 0; i < dgclass->count_methods; i++) {
                MonoObject *obj = mono_array_get (methods, gpointer, i);
 
-               dginst->methods [i] = inflate_method (type, obj);
+               dgclass->methods [i] = inflate_method (type, obj);
        }
 
-       for (i = 0; i < dginst->count_ctors; i++) {
+       for (i = 0; i < dgclass->count_ctors; i++) {
                MonoObject *obj = mono_array_get (ctors, gpointer, i);
 
-               dginst->ctors [i] = inflate_method (type, obj);
+               dgclass->ctors [i] = inflate_method (type, obj);
        }
 
-       for (i = 0; i < dginst->count_fields; i++) {
+       for (i = 0; i < dgclass->count_fields; i++) {
                MonoObject *obj = mono_array_get (fields, gpointer, i);
                MonoClassField *field;
                MonoInflatedField *ifield;
@@ -8006,14 +8191,14 @@ mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoAr
                ifield->generic_type = field->type;
                ifield->reflection_info = obj;
 
-               dginst->fields [i] = *field;
-               dginst->fields [i].generic_info = ifield;
-               dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
+               dgclass->fields [i] = *field;
+               dgclass->fields [i].generic_info = ifield;
+               dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
        }
 
-       for (i = 0; i < dginst->count_properties; i++) {
+       for (i = 0; i < dgclass->count_properties; i++) {
                MonoObject *obj = mono_array_get (properties, gpointer, i);
-               MonoProperty *property = &dginst->properties [i];
+               MonoProperty *property = &dgclass->properties [i];
 
                if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
                        MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
@@ -8036,9 +8221,9 @@ mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoAr
                        g_assert_not_reached ();
        }
 
-       for (i = 0; i < dginst->count_events; i++) {
+       for (i = 0; i < dgclass->count_events; i++) {
                MonoObject *obj = mono_array_get (events, gpointer, i);
-               MonoEvent *event = &dginst->events [i];
+               MonoEvent *event = &dgclass->events [i];
 
                if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
                        MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
@@ -8061,7 +8246,7 @@ mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoAr
                        g_assert_not_reached ();
        }
 
-       ginst->initialized = TRUE;
+       gclass->initialized = TRUE;
 }
 
 static void
@@ -8088,7 +8273,6 @@ ensure_runtime_vtable (MonoClass *klass)
        for (i = 0; i < num; ++i)
                klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
 
-       klass->wastypebuilder = TRUE;
        if (tb->interfaces) {
                klass->interface_count = mono_array_length (tb->interfaces);
                klass->interfaces = g_new (MonoClass*, klass->interface_count);
@@ -8113,7 +8297,7 @@ ensure_runtime_vtable (MonoClass *klass)
                }
        }
 
-       overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
+       overrides = g_new0 (MonoMethod*, onum * 2);
 
        if (tb->methods) {
                onum = 0;
@@ -8135,6 +8319,7 @@ ensure_runtime_vtable (MonoClass *klass)
        }
 
        mono_class_setup_vtable (klass, overrides, onum);
+       g_free (overrides);
 }
 
 static void
@@ -8335,10 +8520,10 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
 
        typebuilder_setup_events (klass);
 
+       klass->wastypebuilder = TRUE;
+
        res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
-       /* with enums res == tb: need to fix that. */
-       if (!klass->enumtype)
-               g_assert (res != (MonoReflectionType*)tb);
+       g_assert (res != (MonoReflectionType*)tb);
        return res;
 }
 
@@ -8352,6 +8537,29 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam
 
        param = g_new0 (MonoGenericParam, 1);
 
+       if (gparam->mbuilder) {
+               if (!gparam->mbuilder->generic_container)
+                       gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
+               param->owner = gparam->mbuilder->generic_container;
+       } else if (gparam->tbuilder) {
+               MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
+               MonoGenericContainer *container = gparam->tbuilder->generic_container;
+
+               while (nesting) {
+                       int count;
+
+                       count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
+                       if (gparam->index >= count)
+                               break;
+
+                       container = nesting->generic_container;
+                       nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
+               }
+
+               g_assert (container);
+               param->owner = container;
+       }
+
        param->method = NULL;
        param->name = mono_string_to_utf8 (gparam->name);
        param->num = gparam->index;
@@ -8463,7 +8671,7 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
 /**
  * mono_reflection_lookup_dynamic_token:
  *
- *  Finish the Builder object pointed to by TOKEN and return the corresponding
+ * Finish the Builder object pointed to by TOKEN and return the corresponding
  * runtime structure.
  */
 gpointer
@@ -8509,7 +8717,7 @@ resolve_object (MonoImage *image, MonoObject *obj)
                         * Hopefully this has been filled in by calling CreateType() on the
                         * TypeBuilder.
                         */
-                       /**
+                       /*
                         * TODO: This won't work if the application finishes another 
                         * TypeBuilder instance instead of this one.
                         */
@@ -8590,3 +8798,119 @@ resolve_object (MonoImage *image, MonoObject *obj)
        return result;
 }
 
+
+/* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
+const static guint32 declsec_flags_map[] = {
+       0x00000000,                                     /* empty */
+       MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
+       MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
+       MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
+       MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
+       MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
+       MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
+       MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
+       MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
+       MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
+       MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
+       MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
+       MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
+       MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
+       MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
+       MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
+       MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
+       MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
+       MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
+};
+
+/*
+ * Returns flags that includes all available security action associated to the handle.
+ * @token: metadata token (either for a class or a method)
+ * @image: image where resides the metadata.
+ */
+static guint32
+mono_declsec_get_flags (MonoImage *image, guint32 token)
+{
+       guint32 index = mono_metadata_declsec_from_index (image, token);
+       MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
+       guint32 result = 0;
+       guint32 action;
+       int i;
+
+       for (i = index; i < t->rows; i++) {
+               guint32 cols [MONO_DECL_SECURITY_SIZE];
+
+               mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
+               if (cols [MONO_DECL_SECURITY_PARENT] != token)
+                       break;
+
+               action = cols [MONO_DECL_SECURITY_ACTION];
+               if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
+                       result |= declsec_flags_map [action];
+               } else {
+                       g_assert_not_reached ();
+               }
+       }
+       return result;
+}
+
+/*
+ * Get the security actions (in the form of flags) associated with the specified method.
+ *
+ * @method: The method for which we want the declarative security flags.
+ * Return the declarative security flags for the method (only).
+ *
+ * Note: To keep MonoMethod size down we do not cache the declarative security flags
+ *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
+ */
+guint32
+mono_declsec_flags_from_method (MonoMethod *method)
+{
+       if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
+               /* FIXME: No cache (for the moment) */
+               guint32 idx = find_method_index (method);
+               idx <<= MONO_HAS_DECL_SECURITY_BITS;
+               idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
+               return mono_declsec_get_flags (method->klass->image, idx);
+       }
+       return 0;
+}
+
+/*
+ * Get the security actions (in the form of flags) associated with the specified class.
+ *
+ * @klass: The class for which we want the declarative security flags.
+ * Return the declarative security flags for the class.
+ *
+ * Note: We cache the flags inside the MonoClass structure as this will get 
+ *       called very often (at least for each method).
+ */
+guint32
+mono_declsec_flags_from_class (MonoClass *klass)
+{
+       if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
+               if (!klass->declsec_flags) {
+                       guint32 idx = mono_metadata_token_index (klass->type_token);
+                       idx <<= MONO_HAS_DECL_SECURITY_BITS;
+                       idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
+                       /* we cache the flags on classes */
+                       klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
+               }
+               return klass->declsec_flags;
+       }
+       return 0;
+}
+
+/*
+ * Get the security actions (in the form of flags) associated with the specified assembly.
+ *
+ * @assembly: The assembly for which we want the declarative security flags.
+ * Return the declarative security flags for the assembly.
+ */
+guint32
+mono_declsec_flags_from_assembly (MonoAssembly *assembly)
+{
+       guint32 idx = 1; /* there is only one assembly */
+       idx <<= MONO_HAS_DECL_SECURITY_BITS;
+       idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
+       return mono_declsec_get_flags (assembly->image, idx);
+}