2008-02-28 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / reflection.c
index ad5bce4e58497c8f86dbf742aec903ea11b517ff..14b0ab443b6d52f6f0bf0ebfe187f34ac11e9652 100644 (file)
@@ -12,6 +12,7 @@
 #include "mono/metadata/reflection.h"
 #include "mono/metadata/tabledefs.h"
 #include "mono/metadata/metadata-internals.h"
+#include <mono/metadata/profiler-private.h>
 #include "mono/metadata/class-internals.h"
 #include "mono/metadata/gc-internal.h"
 #include "mono/metadata/tokentype.h"
 #include "cil-coff.h"
 #include "rawbuffer.h"
 #include "mono-endian.h"
-#include <mono/os/gc_wrapper.h>
+#include <mono/metadata/gc-internal.h>
+
+typedef struct {
+       char *p;
+       char *buf;
+       char *end;
+} SigBuffer;
 
 #define TEXT_OFFSET 512
 #define CLI_H_SIZE 136
@@ -128,6 +135,7 @@ const unsigned char table_sizes [MONO_TABLE_NUM] = {
 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);
+static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
@@ -137,12 +145,72 @@ static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMa
 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
 static void    ensure_runtime_vtable (MonoClass *klass);
-static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class);
-static void    encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
-static guint32 type_get_signature_size (MonoType *type);
+static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
+static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
-static inline MonoType *dup_type (const MonoType *original);
+static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
+static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
+
+#define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
+#define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
+static CRITICAL_SECTION reflection_mutex;
+
+void
+mono_reflection_init (void)
+{
+       InitializeCriticalSection (&reflection_mutex);
+}
+
+static void
+sigbuffer_init (SigBuffer *buf, int size)
+{
+       buf->buf = g_malloc (size);
+       buf->p = buf->buf;
+       buf->end = buf->buf + size;
+}
+
+static void
+sigbuffer_make_room (SigBuffer *buf, int size)
+{
+       if (buf->end - buf->p < size) {
+               int new_size = buf->end - buf->buf + size + 32;
+               char *p = g_realloc (buf->buf, new_size);
+               size = buf->p - buf->buf;
+               buf->buf = p;
+               buf->p = p + size;
+               buf->end = buf->buf + new_size;
+       }
+}
+
+static void
+sigbuffer_add_value (SigBuffer *buf, guint32 val)
+{
+       sigbuffer_make_room (buf, 6);
+       mono_metadata_encode_value (val, buf->p, &buf->p);
+}
+
+static void
+sigbuffer_add_byte (SigBuffer *buf, guint8 val)
+{
+       sigbuffer_make_room (buf, 1);
+       buf->p [0] = val;
+       buf->p++;
+}
+
+static void
+sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
+{
+       sigbuffer_make_room (buf, size);
+       memcpy (buf->p, p, size);
+       buf->p += size;
+}
+
+static void
+sigbuffer_free (SigBuffer *buf)
+{
+       g_free (buf->buf);
+}
 
 /**
  * mp_g_alloc:
@@ -174,6 +242,21 @@ mp_g_malloc0 (MonoMemPool *mp, guint size)
                return g_malloc0 (size);
 }
 
+/**
+ * mp_string_to_utf8:
+ *
+ * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
+ * memory from the C heap.
+ */
+static char *
+mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
+{
+       if (mp)
+               return mono_string_to_utf8_mp (mp, s);
+       else
+               return mono_string_to_utf8 (s);
+}
+
 #define mp_g_new(mp,struct_type, n_structs)            \
     ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
 
@@ -348,6 +431,18 @@ add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int
        return idx;
 }
 
+static guint32
+sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
+{
+       char blob_size [8];
+       char *b = blob_size;
+       guint32 size = buf->p - buf->buf;
+       /* store length */
+       g_assert (size <= (buf->end - buf->buf));
+       mono_metadata_encode_value (size, b, &b);
+       return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
+}
+
 /*
  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
  * dest may be misaligned.
@@ -475,7 +570,7 @@ default_class_from_mono_type (MonoType *type)
        case MONO_TYPE_STRING:
                return mono_defaults.string_class;
        default:
-               g_warning ("implement me 0x%02x\n", type->type);
+               g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
                g_assert_not_reached ();
        }
        
@@ -483,26 +578,29 @@ default_class_from_mono_type (MonoType *type)
 }
 
 static void
-encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
+encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
 {
        int i;
+       MonoGenericInst *class_inst;
+       MonoClass *klass;
 
-       if (!gclass) {
-               g_assert_not_reached ();
-               return;
-       }
+       g_assert (gclass);
 
-       mono_metadata_encode_value (MONO_TYPE_GENERICINST, 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);
+       class_inst = gclass->context.class_inst;
+
+       sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
+       klass = gclass->container_class;
+       sigbuffer_add_value (buf, klass->byval_arg.type);
+       sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
+
+       sigbuffer_add_value (buf, class_inst->type_argc);
+       for (i = 0; i < class_inst->type_argc; ++i)
+               encode_type (assembly, class_inst->type_argv [i], buf);
 
-       *endbuf = p;
 }
 
 static void
-encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
+encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
 {
        if (!type) {
                g_assert_not_reached ();
@@ -510,7 +608,7 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
        }
                
        if (type->byref)
-               mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
+               sigbuffer_add_value (buf, MONO_TYPE_BYREF);
 
        switch (type->type){
        case MONO_TYPE_VOID:
@@ -531,61 +629,68 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
        case MONO_TYPE_STRING:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_TYPEDBYREF:
-               mono_metadata_encode_value (type->type, p, &p);
+               sigbuffer_add_value (buf, type->type);
                break;
        case MONO_TYPE_PTR:
-               mono_metadata_encode_value (type->type, p, &p);
-               encode_type (assembly, type->data.type, p, &p);
+               sigbuffer_add_value (buf, type->type);
+               encode_type (assembly, type->data.type, buf);
                break;
        case MONO_TYPE_SZARRAY:
-               mono_metadata_encode_value (type->type, p, &p);
-               encode_type (assembly, &type->data.klass->byval_arg, p, &p);
+               sigbuffer_add_value (buf, type->type);
+               encode_type (assembly, &type->data.klass->byval_arg, buf);
                break;
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_CLASS: {
                MonoClass *k = mono_class_from_mono_type (type);
-               /*
-                * Make sure we use the correct type.
-                */
-               mono_metadata_encode_value (k->byval_arg.type, p, &p);
-               /*
-                * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
-                * otherwise two typerefs could point to the same type, leading to
-                * verification errors.
-                */
-               mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
+
+               if (k->generic_container) {
+                       MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
+                       encode_generic_class (assembly, gclass, buf);
+               } else {
+                       /*
+                        * Make sure we use the correct type.
+                        */
+                       sigbuffer_add_value (buf, k->byval_arg.type);
+                       /*
+                        * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
+                        * otherwise two typerefs could point to the same type, leading to
+                        * verification errors.
+                        */
+                       sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
+               }
                break;
        }
        case MONO_TYPE_ARRAY:
-               mono_metadata_encode_value (type->type, p, &p);
-               encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
-               mono_metadata_encode_value (type->data.array->rank, p, &p);
-               mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
-               mono_metadata_encode_value (0, p, &p);
+               sigbuffer_add_value (buf, type->type);
+               encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
+               sigbuffer_add_value (buf, type->data.array->rank);
+               sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
+               sigbuffer_add_value (buf, 0);
                break;
        case MONO_TYPE_GENERICINST:
-               encode_generic_class (assembly, type->data.generic_class, p, &p);
+               encode_generic_class (assembly, type->data.generic_class, buf);
                break;
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
-               mono_metadata_encode_value (type->type, p, &p);
-               mono_metadata_encode_value (type->data.generic_param->num, p, &p);
+               sigbuffer_add_value (buf, type->type);
+               sigbuffer_add_value (buf, type->data.generic_param->num);
                break;
        default:
                g_error ("need to encode type %x", type->type);
        }
-       *endbuf = p;
 }
 
 static void
-encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
+encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
 {
        if (!type) {
-               mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
+               sigbuffer_add_value (buf, MONO_TYPE_VOID);
                return;
        }
-       if (type->type) {
-               encode_type (assembly, type->type, p, endbuf);
+
+       if (type->type ||
+            ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
+               encode_type (assembly, type->type, buf);
                return;
        }
 
@@ -594,156 +699,58 @@ encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, ch
 }
 
 static void
-encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
+encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
 {
        int i;
 
        if (modreq) {
                for (i = 0; i < mono_array_length (modreq); ++i) {
                        MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
-                       *p = MONO_TYPE_CMOD_REQD;
-                       p++;
-                       mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
+                       sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
+                       sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
                }
        }
        if (modopt) {
                for (i = 0; i < mono_array_length (modopt); ++i) {
                        MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
-                       *p = MONO_TYPE_CMOD_OPT;
-                       p++;
-                       mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
+                       sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
+                       sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
                }
        }
-       *endbuf = p;
-}
-
-static guint32
-generic_class_get_signature_size (MonoGenericClass *gclass)
-{
-       guint32 size = 0;
-       int i;
-
-       if (!gclass) {
-               g_assert_not_reached ();
-       }
-
-       size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
-       size += 4;
-       for (i = 0; i < gclass->inst->type_argc; ++i)
-               size += type_get_signature_size (gclass->inst->type_argv [i]);
-
-       return size;
-}
-
-static guint32
-type_get_signature_size (MonoType *type)
-{
-       guint32 size = 0;
-
-       if (!type) {
-               g_assert_not_reached ();
-       }
-               
-       if (type->byref)
-               size++;
-
-       switch (type->type){
-       case MONO_TYPE_VOID:
-       case MONO_TYPE_BOOLEAN:
-       case MONO_TYPE_CHAR:
-       case MONO_TYPE_I1:
-       case MONO_TYPE_U1:
-       case MONO_TYPE_I2:
-       case MONO_TYPE_U2:
-       case MONO_TYPE_I4:
-       case MONO_TYPE_U4:
-       case MONO_TYPE_I8:
-       case MONO_TYPE_U8:
-       case MONO_TYPE_R4:
-       case MONO_TYPE_R8:
-       case MONO_TYPE_I:
-       case MONO_TYPE_U:
-       case MONO_TYPE_STRING:
-       case MONO_TYPE_OBJECT:
-       case MONO_TYPE_TYPEDBYREF:
-               return size + 1;
-       case MONO_TYPE_PTR:
-               return size + 1 + type_get_signature_size (type->data.type);
-       case MONO_TYPE_SZARRAY:
-               return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
-       case MONO_TYPE_VALUETYPE:
-       case MONO_TYPE_CLASS:
-               return size + 5;
-       case MONO_TYPE_ARRAY:
-               return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
-       case MONO_TYPE_GENERICINST:
-               return size + generic_class_get_signature_size (type->data.generic_class);
-       case MONO_TYPE_VAR:
-       case MONO_TYPE_MVAR:
-               return size + 5;
-       default:
-               g_error ("need to encode type %x", type->type);
-               return size;
-       }
-}
-
-static guint32
-method_get_signature_size (MonoMethodSignature *sig)
-{
-       guint32 size;
-       int i;
-
-       size = type_get_signature_size (sig->ret);
-       for (i = 0; i < sig->param_count; i++)
-               size += type_get_signature_size (sig->params [i]);
-
-       if (sig->generic_param_count)
-               size += 4;
-       if (sig->sentinelpos >= 0)
-               size++;
-
-       return size;    
 }
 
 static guint32
 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
 {
-       char *buf;
-       char *p;
+       SigBuffer buf;
        int i;
        guint32 nparams =  sig->param_count;
-       guint32 size = 11 + method_get_signature_size (sig);
        guint32 idx;
-       char blob_size [6];
-       char *b = blob_size;
 
        if (!assembly->save)
                return 0;
 
-       p = buf = g_malloc (size);
+       sigbuffer_init (&buf, 32);
        /*
         * FIXME: vararg, explicit_this, differenc call_conv values...
         */
-       *p = sig->call_convention;
+       idx = sig->call_convention;
        if (sig->hasthis)
-               *p |= 0x20; /* hasthis */
+               idx |= 0x20; /* hasthis */
        if (sig->generic_param_count)
-               *p |= 0x10; /* generic */
-       p++;
+               idx |= 0x10; /* generic */
+       sigbuffer_add_byte (&buf, idx);
        if (sig->generic_param_count)
-               mono_metadata_encode_value (sig->generic_param_count, p, &p);
-       mono_metadata_encode_value (nparams, p, &p);
-       encode_type (assembly, sig->ret, p, &p);
+               sigbuffer_add_value (&buf, sig->generic_param_count);
+       sigbuffer_add_value (&buf, nparams);
+       encode_type (assembly, sig->ret, &buf);
        for (i = 0; i < nparams; ++i) {
                if (i == sig->sentinelpos)
-                       *p++ = MONO_TYPE_SENTINEL;
-               encode_type (assembly, sig->params [i], p, &p);
+                       sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
+               encode_type (assembly, sig->params [i], &buf);
        }
-       /* store length */
-       g_assert (p - buf < size);
-       mono_metadata_encode_value (p-buf, b, &b);
-       idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
-       g_free (buf);
+       idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+       sigbuffer_free (&buf);
        return idx;
 }
 
@@ -753,32 +760,28 @@ method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBui
        /*
         * FIXME: reuse code from method_encode_signature().
         */
-       char *buf;
-       char *p;
+       SigBuffer buf;
        int i;
        guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
        guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
        guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
-       guint32 size = 41 + nparams * 40 + notypes * 40;
        guint32 idx;
-       char blob_size [6];
-       char *b = blob_size;
 
-       p = buf = g_malloc (size);
+       sigbuffer_init (&buf, 32);
        /* LAMESPEC: all the call conv spec is foobared */
-       *p = mb->call_conv & 0x60; /* has-this, explicit-this */
+       idx = mb->call_conv & 0x60; /* has-this, explicit-this */
        if (mb->call_conv & 2)
-               *p |= 0x5; /* vararg */
+               idx |= 0x5; /* vararg */
        if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
-               *p |= 0x20; /* hasthis */
+               idx |= 0x20; /* hasthis */
        if (ngparams)
-               *p |= 0x10; /* generic */
-       p++;
+               idx |= 0x10; /* generic */
+       sigbuffer_add_byte (&buf, idx);
        if (ngparams)
-               mono_metadata_encode_value (ngparams, p, &p);
-       mono_metadata_encode_value (nparams + notypes, p, &p);
-       encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
-       encode_reflection_type (assembly, mb->rtype, p, &p);
+               sigbuffer_add_value (&buf, ngparams);
+       sigbuffer_add_value (&buf, nparams + notypes);
+       encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
+       encode_reflection_type (assembly, mb->rtype, &buf);
        for (i = 0; i < nparams; ++i) {
                MonoArray *modreq = NULL;
                MonoArray *modopt = NULL;
@@ -788,24 +791,21 @@ method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBui
                        modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
                if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
                        modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
-               encode_custom_modifiers (assembly, modreq, modopt, p, &p);
+               encode_custom_modifiers (assembly, modreq, modopt, &buf);
                pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
-               encode_reflection_type (assembly, pt, p, &p);
+               encode_reflection_type (assembly, pt, &buf);
        }
        if (notypes)
-               *p++ = MONO_TYPE_SENTINEL;
+               sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
        for (i = 0; i < notypes; ++i) {
                MonoReflectionType *pt;
 
                pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
-               encode_reflection_type (assembly, pt, p, &p);
+               encode_reflection_type (assembly, pt, &buf);
        }
 
-       /* store length */
-       g_assert (p - buf < size);
-       mono_metadata_encode_value (p-buf, b, &b);
-       idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
-       g_free (buf);
+       idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+       sigbuffer_free (&buf);
        return idx;
 }
 
@@ -814,36 +814,30 @@ encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
 {
        MonoDynamicTable *table;
        guint32 *values;
-       char *p;
-       guint32 idx, sig_idx, size;
+       guint32 idx, sig_idx;
        guint nl = mono_array_length (ilgen->locals);
-       char *buf;
-       char blob_size [6];
-       char *b = blob_size;
+       SigBuffer buf;
        int i;
 
-       size = 50 + nl * 30;
-       p = buf = g_malloc (size);
+       sigbuffer_init (&buf, 32);
        table = &assembly->tables [MONO_TABLE_STANDALONESIG];
        idx = table->next_idx ++;
        table->rows ++;
        alloc_table (table, table->rows);
        values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
 
-       mono_metadata_encode_value (0x07, p, &p);
-       mono_metadata_encode_value (nl, p, &p);
+       sigbuffer_add_value (&buf, 0x07);
+       sigbuffer_add_value (&buf, nl);
        for (i = 0; i < nl; ++i) {
                MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
                
                if (lb->is_pinned)
-                       mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
+                       sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
                
-               encode_reflection_type (assembly, lb->type, p, &p);
+               encode_reflection_type (assembly, lb->type, &buf);
        }
-       g_assert (p - buf < size);
-       mono_metadata_encode_value (p-buf, b, &b);
-       sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
-       g_free (buf);
+       sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+       sigbuffer_free (&buf);
 
        values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
 
@@ -1021,7 +1015,7 @@ fat_header:
                sheader [1] = num_exception & 0xff;
                sheader [2] = (num_exception >> 8) & 0xff;
                sheader [3] = (num_exception >> 16) & 0xff;
-               mono_image_add_stream_data (&assembly->code, sheader, 4);
+               mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
                /* fat header, so we are already aligned */
                /* reverse order */
                for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
@@ -1091,8 +1085,31 @@ find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32
        return 0;
 }
 
+/* protected by reflection_mutex: 
+ * maps a mono runtime reflection handle to MonoCustomAttrInfo*
+ */
 static GHashTable *dynamic_custom_attrs = NULL;
 
+static MonoCustomAttrInfo*
+lookup_custom_attr (void *member)
+{
+       MonoCustomAttrInfo *ainfo, *res;
+       int size;
+
+       mono_reflection_lock ();
+       ainfo = g_hash_table_lookup (dynamic_custom_attrs, member);
+       mono_reflection_unlock ();
+
+       if (ainfo) {
+               /* Need to copy since it will be freed later */
+               size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
+               res = g_malloc0 (size);
+               memcpy (res, ainfo, size);
+               return res;
+       }
+       return NULL;
+}
+
 static gboolean
 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
 {
@@ -1135,16 +1152,19 @@ mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
        ainfo->image = image;
        ainfo->num_attrs = count;
        index = 0;
+       mono_loader_lock ();
        for (i = 0; i < count; ++i) {
                cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
                if (custom_attr_visible (image, cattr)) {
+                       unsigned char *saved = mono_mempool_alloc (image->mempool, mono_array_length (cattr->data));
+                       memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
                        ainfo->attrs [index].ctor = cattr->ctor->method;
-                       /* FIXME: might want to memdup the data here */
-                       ainfo->attrs [index].data = mono_array_addr (cattr->data, char, 0);
+                       ainfo->attrs [index].data = saved;
                        ainfo->attrs [index].data_size = mono_array_length (cattr->data);
                        index ++;
                }
        }
+       mono_loader_unlock ();
 
        return ainfo;
 }
@@ -1157,11 +1177,13 @@ mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
        if (!ainfo)
                return;
 
+       mono_reflection_lock ();
        if (!dynamic_custom_attrs)
                dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
 
        g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
        ainfo->cached = TRUE;
+       mono_reflection_unlock ();
 }
 
 void
@@ -1348,6 +1370,8 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly
 static void
 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
 {
+       memset (rmb, 0, sizeof (ReflectionMethodBuilder));
+
        rmb->ilgen = mb->ilgen;
        rmb->rtype = mb->rtype;
        rmb->parameters = mb->parameters;
@@ -1363,6 +1387,7 @@ reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, Mono
        rmb->name = mb->name;
        rmb->table_idx = &mb->table_idx;
        rmb->init_locals = mb->init_locals;
+       rmb->skip_visibility = FALSE;
        rmb->return_modreq = mb->return_modreq;
        rmb->return_modopt = mb->return_modopt;
        rmb->param_modreq = mb->param_modreq;
@@ -1386,6 +1411,8 @@ reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoRe
 {
        const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
 
+       memset (rmb, 0, sizeof (ReflectionMethodBuilder));
+
        rmb->ilgen = mb->ilgen;
        rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
        rmb->parameters = mb->parameters;
@@ -1401,6 +1428,7 @@ reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoRe
        rmb->name = mono_string_new (mono_domain_get (), name);
        rmb->table_idx = &mb->table_idx;
        rmb->init_locals = mb->init_locals;
+       rmb->skip_visibility = FALSE;
        rmb->return_modreq = NULL;
        rmb->return_modopt = NULL;
        rmb->param_modreq = mb->param_modreq;
@@ -1414,6 +1442,8 @@ reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoRe
 static void
 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
 {
+       memset (rmb, 0, sizeof (ReflectionMethodBuilder));
+
        rmb->ilgen = mb->ilgen;
        rmb->rtype = mb->rtype;
        rmb->parameters = mb->parameters;
@@ -1425,7 +1455,7 @@ reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, Mono
        rmb->iattrs = 0;
        rmb->call_conv = mb->call_conv;
        rmb->code = NULL;
-       rmb->type = NULL;
+       rmb->type = (MonoObject *) mb->owner;
        rmb->name = mb->name;
        rmb->table_idx = NULL;
        rmb->init_locals = mb->init_locals;
@@ -1551,8 +1581,12 @@ type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
        if (!klass) 
                return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
        ta = klass->image->assembly;
-       if (ta->dynamic || (ta == ass))
-               return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
+       if (ta->dynamic || (ta == ass)) {
+               if (klass->generic_class)
+                       return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
+               else
+                       return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
+       }
 
        return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
 }
@@ -1560,46 +1594,36 @@ type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
 static guint32
 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
 {
-       char blob_size [64];
-       char *b = blob_size;
-       char *p;
-       char* buf;
+       SigBuffer buf;
        guint32 idx;
 
        if (!assembly->save)
                return 0;
 
-       p = buf = g_malloc (256);
+       sigbuffer_init (&buf, 32);
        
-       mono_metadata_encode_value (0x06, p, &p);
+       sigbuffer_add_value (&buf, 0x06);
        /* encode custom attributes before the type */
-       encode_type (assembly, type, p, &p);
-       g_assert (p-buf < 256);
-       mono_metadata_encode_value (p-buf, b, &b);
-       idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
-       g_free (buf);
+       encode_type (assembly, type, &buf);
+       idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+       sigbuffer_free (&buf);
        return idx;
 }
 
 static guint32
 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
 {
-       char blob_size [64];
-       char *b = blob_size;
-       char *p;
-       char* buf;
+       SigBuffer buf;
        guint32 idx;
+
+       sigbuffer_init (&buf, 32);
        
-       p = buf = g_malloc (256);
-       
-       mono_metadata_encode_value (0x06, p, &p);
-       encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
+       sigbuffer_add_value (&buf, 0x06);
+       encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
        /* encode custom attributes before the type */
-       encode_reflection_type (assembly, fb->type, p, &p);
-       g_assert (p-buf < 256);
-       mono_metadata_encode_value (p-buf, b, &b);
-       idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
-       g_free (buf);
+       encode_reflection_type (assembly, fb->type, &buf);
+       idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+       sigbuffer_free (&buf);
        return idx;
 }
 
@@ -1687,6 +1711,9 @@ handle_enum:
                g_free (buf);
                return idx;
        }
+       case MONO_TYPE_GENERICINST:
+               *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
+               goto handle_enum;
        default:
                g_error ("we don't encode constant type 0x%02x yet", *ret_type);
        }
@@ -1707,38 +1734,28 @@ handle_enum:
 
 static guint32
 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
-       char blob_size [64];
-       char *b = blob_size;
-       char *p, *buf, *str;
-       guint32 idx, len, bufsize = 256;
-       
-       p = buf = g_malloc (bufsize);
+       char *str;
+       SigBuffer buf;
+       guint32 idx, len;
 
-       mono_metadata_encode_value (minfo->type, p, &p);
+       sigbuffer_init (&buf, 32);
+
+       sigbuffer_add_value (&buf, minfo->type);
 
        switch (minfo->type) {
        case MONO_NATIVE_BYVALTSTR:
        case MONO_NATIVE_BYVALARRAY:
-               mono_metadata_encode_value (minfo->count, p, &p);
+               sigbuffer_add_value (&buf, minfo->count);
                break;
        case MONO_NATIVE_LPARRAY:
                if (minfo->eltype || minfo->has_size) {
-                       mono_metadata_encode_value (minfo->eltype, p, &p);
+                       sigbuffer_add_value (&buf, minfo->eltype);
                        if (minfo->has_size) {
-                               if (minfo->param_num != -1)
-                                       mono_metadata_encode_value (minfo->param_num, p, &p);
-                               else
-                                       mono_metadata_encode_value (0, p, &p);
-                               if (minfo->count != -1)
-                                       mono_metadata_encode_value (minfo->count, p, &p);
-                               else
-                                       mono_metadata_encode_value (0, p, &p);
+                               sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
+                               sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
 
                                /* LAMESPEC: ElemMult is undocumented */
-                               if (minfo->param_num != -1)
-                                       mono_metadata_encode_value (1, p, &p);
-                               else
-                                       mono_metadata_encode_value (0, p, &p);
+                               sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
                        }
                }
                break;
@@ -1746,15 +1763,14 @@ encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
                if (minfo->guid) {
                        str = mono_string_to_utf8 (minfo->guid);
                        len = strlen (str);
-                       mono_metadata_encode_value (len, p, &p);
-                       memcpy (p, str, len);
-                       p += len;
+                       sigbuffer_add_value (&buf, len);
+                       sigbuffer_add_mem (&buf, str, len);
                        g_free (str);
                } else {
-                       mono_metadata_encode_value (0, p, &p);
+                       sigbuffer_add_value (&buf, 0);
                }
                /* native type name */
-               mono_metadata_encode_value (0, p, &p);
+               sigbuffer_add_value (&buf, 0);
                /* custom marshaler type name */
                if (minfo->marshaltype || minfo->marshaltyperef) {
                        if (minfo->marshaltyperef)
@@ -1762,44 +1778,28 @@ encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
                        else
                                str = mono_string_to_utf8 (minfo->marshaltype);
                        len = strlen (str);
-                       mono_metadata_encode_value (len, p, &p);
-                       if (p + len >= buf + bufsize) {
-                               idx = p - buf;
-                               bufsize *= 2;
-                               buf = g_realloc (buf, bufsize);
-                               p = buf + idx;
-                       }
-                       memcpy (p, str, len);
-                       p += len;
+                       sigbuffer_add_value (&buf, len);
+                       sigbuffer_add_mem (&buf, str, len);
                        g_free (str);
                } else {
                        /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
-                       mono_metadata_encode_value (0, p, &p);
+                       sigbuffer_add_value (&buf, 0);
                }
                if (minfo->mcookie) {
                        str = mono_string_to_utf8 (minfo->mcookie);
                        len = strlen (str);
-                       mono_metadata_encode_value (len, p, &p);
-                       if (p + len >= buf + bufsize) {
-                               idx = p - buf;
-                               bufsize *= 2;
-                               buf = g_realloc (buf, bufsize);
-                               p = buf + idx;
-                       }
-                       memcpy (p, str, len);
-                       p += len;
+                       sigbuffer_add_value (&buf, len);
+                       sigbuffer_add_mem (&buf, str, len);
                        g_free (str);
                } else {
-                       mono_metadata_encode_value (0, p, &p);
+                       sigbuffer_add_value (&buf, 0);
                }
                break;
        default:
                break;
        }
-       len = p-buf;
-       mono_metadata_encode_value (len, b, &b);
-       idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
-       g_free (buf);
+       idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+       sigbuffer_free (&buf);
        return idx;
 }
 
@@ -1849,9 +1849,11 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *ass
                /*
                 * We store it in the code section because it's simpler for now.
                 */
-               if (fb->rva_data)
+               if (fb->rva_data) {
+                       if (mono_array_length (fb->rva_data) >= 10)
+                               stream_data_align (&assembly->code);
                        rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
-               else
+               else
                        rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
                values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
        }
@@ -1868,46 +1870,38 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *ass
 static guint32
 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
 {
-       char *buf, *p;
-       char blob_size [6];
-       char *b = blob_size;
+       SigBuffer buf;
        guint32 nparams = 0;
        MonoReflectionMethodBuilder *mb = fb->get_method;
        MonoReflectionMethodBuilder *smb = fb->set_method;
-       guint32 idx, i, size;
+       guint32 idx, i;
 
        if (mb && mb->parameters)
                nparams = mono_array_length (mb->parameters);
        if (!mb && smb && smb->parameters)
                nparams = mono_array_length (smb->parameters) - 1;
-       size = 24 + nparams * 10;
-       buf = p = g_malloc (size);
-       *p = 0x08;
-       p++;
-       mono_metadata_encode_value (nparams, p, &p);
+       sigbuffer_init (&buf, 32);
+       sigbuffer_add_byte (&buf, 0x08);
+       sigbuffer_add_value (&buf, nparams);
        if (mb) {
-               encode_reflection_type (assembly, mb->rtype, p, &p);
+               encode_reflection_type (assembly, mb->rtype, &buf);
                for (i = 0; i < nparams; ++i) {
                        MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
-                       encode_reflection_type (assembly, pt, p, &p);
+                       encode_reflection_type (assembly, pt, &buf);
                }
        } else if (smb && smb->parameters) {
                /* the property type is the last param */
-               encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
+               encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
                for (i = 0; i < nparams; ++i) {
                        MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
-                       encode_reflection_type (assembly, pt, p, &p);
+                       encode_reflection_type (assembly, pt, &buf);
                }
-       }
-       else {
-               encode_reflection_type (assembly, fb->type, p, &p);
+       } else {
+               encode_reflection_type (assembly, fb->type, &buf);
        }
 
-       /* store length */
-       g_assert (p - buf < size);
-       mono_metadata_encode_value (p-buf, b, &b);
-       idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
-       g_free (buf);
+       idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+       sigbuffer_free (&buf);
        return idx;
 }
 
@@ -2157,8 +2151,8 @@ resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
        if ((pubkey = mono_image_get_public_key (image, &publen))) {
                guchar pubtoken [9];
                pubtoken [0] = 8;
-               mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
-               values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
+               mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
+               values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
        } else {
                values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
        }
@@ -2174,11 +2168,12 @@ create_typespec (MonoDynamicImage *assembly, MonoType *type)
        MonoDynamicTable *table;
        guint32 *values;
        guint32 token;
-       char sig [128];
-       char *p = sig;
-       char blob_size [6];
-       char *b = blob_size;
+       SigBuffer buf;
+
+       if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
+               return token;
 
+       sigbuffer_init (&buf, 32);
        switch (type->type) {
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_PTR:
@@ -2187,51 +2182,50 @@ create_typespec (MonoDynamicImage *assembly, MonoType *type)
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
        case MONO_TYPE_GENERICINST:
-               encode_type (assembly, type, p, &p);
+               encode_type (assembly, type, &buf);
                break;
        case MONO_TYPE_CLASS:
        case MONO_TYPE_VALUETYPE: {
                MonoClass *k = mono_class_from_mono_type (type);
-               if (!k || !k->generic_class)
+               if (!k || !k->generic_container) {
+                       sigbuffer_free (&buf);
                        return 0;
-               encode_generic_class (assembly, k->generic_class, p, &p);
+               }
+               encode_type (assembly, type, &buf);
                break;
        }
        default:
+               sigbuffer_free (&buf);
                return 0;
        }
 
        table = &assembly->tables [MONO_TABLE_TYPESPEC];
        if (assembly->save) {
-               g_assert (p-sig < 128);
-               mono_metadata_encode_value (p-sig, b, &b);
-               token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
+               token = sigbuffer_add_to_blob_cached (assembly, &buf);
                alloc_table (table, table->rows + 1);
                values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
                values [MONO_TYPESPEC_SIGNATURE] = token;
        }
+       sigbuffer_free (&buf);
 
        token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
-       g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
+       g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
        table->next_idx ++;
        return token;
 }
 
-/*
- * Despite the name, we handle also TypeSpec (with the above helper).
- */
 static guint32
-mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
+mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
 {
        MonoDynamicTable *table;
        guint32 *values;
        guint32 token, scope, enclosing;
        MonoClass *klass;
 
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
-       if (token)
+       /* if the type requires a typespec, we must try that first*/
+       if (try_typespec && (token = create_typespec (assembly, type)))
                return token;
-       token = create_typespec (assembly, type);
+       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
        if (token)
                return token;
        klass = my_mono_class_from_mono_type (type);
@@ -2250,7 +2244,7 @@ mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
        }
 
        if (klass->nested_in) {
-               enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
+               enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
                /* get the typeref idx of the enclosing type */
                enclosing >>= MONO_TYPEDEFORREF_BITS;
                scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
@@ -2272,6 +2266,15 @@ mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
        return token;
 }
 
+/*
+ * Despite the name, we handle also TypeSpec (with the above helper).
+ */
+static guint32
+mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
+{
+       return mono_image_typedef_or_ref_full (assembly, type, TRUE);
+}
+
 /*
  * Insert a memberef row into the metadata: the token that point to the memberref
  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
@@ -2421,35 +2424,28 @@ mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *
 }
 
 static guint32
-encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
+encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
 {
-       char *buf;
-       char *p;
+       SigBuffer buf;
        int i;
-       guint32 nparams =  gmethod->inst->type_argc;
-       guint32 size = 10 + nparams * 30;
+       guint32 nparams = context->method_inst->type_argc;
        guint32 idx;
-       char blob_size [6];
-       char *b = blob_size;
 
        if (!assembly->save)
                return 0;
 
-       p = buf = g_malloc (size);
+       sigbuffer_init (&buf, 32);
        /*
         * FIXME: vararg, explicit_this, differenc call_conv values...
         */
-       mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
-       mono_metadata_encode_value (nparams, p, &p);
+       sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
+       sigbuffer_add_value (&buf, nparams);
 
        for (i = 0; i < nparams; i++)
-               encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
+               encode_type (assembly, context->method_inst->type_argv [i], &buf);
 
-       /* store length */
-       g_assert (p - buf < size);
-       mono_metadata_encode_value (p-buf, b, &b);
-       idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
-       g_free (buf);
+       idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+       sigbuffer_free (&buf);
        return idx;
 }
 
@@ -2465,7 +2461,6 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
        table = &assembly->tables [MONO_TABLE_METHODSPEC];
 
        g_assert (method->is_inflated);
-       method = mono_get_inflated_method (method);
        imethod = (MonoMethodInflated *) method;
        declaring = imethod->declaring;
 
@@ -2486,7 +2481,7 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
                g_assert_not_reached ();
        }
 
-       sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
+       sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
 
        if (assembly->save) {
                alloc_table (table, table->rows + 1);
@@ -2505,7 +2500,6 @@ static guint32
 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
 {
        MonoMethodInflated *imethod;
-       MonoMethod *inflated;
        guint32 token;
        
        token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
@@ -2513,16 +2507,15 @@ mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
                return token;
 
        g_assert (method->is_inflated);
-       inflated = mono_get_inflated_method (method);
-       imethod = (MonoMethodInflated *) inflated;
+       imethod = (MonoMethodInflated *) method;
 
        if (mono_method_signature (imethod->declaring)->generic_param_count) {
-               token = method_encode_methodspec (assembly, inflated);
+               token = method_encode_methodspec (assembly, method);
        } else {
                guint32 sig = method_encode_signature (
                        assembly, mono_method_signature (imethod->declaring));
                token = mono_image_get_memberref_token (
-                       assembly, &inflated->klass->byval_arg, inflated->name, sig);
+                       assembly, &method->klass->byval_arg, method->name, sig);
        }
 
        g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
@@ -2535,8 +2528,6 @@ mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
        MonoMethodInflated *imethod = (MonoMethodInflated *) m;
        guint32 sig, token;
 
-       m = mono_get_inflated_method (m);
-
        sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
        token = mono_image_get_memberref_token (
                assembly, &m->klass->byval_arg, m->name, sig);
@@ -2551,10 +2542,7 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *
        MonoClass *klass;
        guint32 *values;
        guint32 token;
-       char sig [128];
-       char *p = sig;
-       char blob_size [6];
-       char *b = blob_size;
+       SigBuffer buf;
        int count, i;
 
        /*
@@ -2567,32 +2555,38 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *
        if (token)
                return token;
 
+       sigbuffer_init (&buf, 32);
+
        g_assert (tb->generic_params);
        klass = mono_class_from_mono_type (tb->type.type);
 
-       mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
-       encode_type (assembly, &klass->byval_arg, p, &p);
+       if (tb->generic_container)
+               mono_reflection_create_generic_class (tb);
+
+       sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
+       g_assert (klass->generic_container);
+       sigbuffer_add_value (&buf, klass->byval_arg.type);
+       sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
 
        count = mono_array_length (tb->generic_params);
-       mono_metadata_encode_value (count, p, &p);
+       sigbuffer_add_value (&buf, count);
        for (i = 0; i < count; i++) {
                MonoReflectionGenericParam *gparam;
 
                gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
 
-               encode_type (assembly, gparam->type.type, p, &p);
+               encode_type (assembly, gparam->type.type, &buf);
        }
 
        table = &assembly->tables [MONO_TABLE_TYPESPEC];
-       g_assert (p-sig < 128);
 
        if (assembly->save) {
-               mono_metadata_encode_value (p-sig, b, &b);
-               token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
+               token = sigbuffer_add_to_blob_cached (assembly, &buf);
                alloc_table (table, table->rows + 1);
                values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
                values [MONO_TYPESPEC_SIGNATURE] = token;
        }
+       sigbuffer_free (&buf);
 
        token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
        g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
@@ -2643,18 +2637,15 @@ mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFi
 static guint32
 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
 {
-       char *buf;
-       char *p;
+       SigBuffer buf;
        guint32 nargs;
        guint32 size;
        guint32 i, idx;
-       char blob_size [6];
-       char *b = blob_size;
 
        if (!assembly->save)
                return 0;
 
-       /* FIXME: */
+       /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
        g_assert (helper->type == 2);
 
        if (helper->arguments)
@@ -2664,7 +2655,7 @@ mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigH
 
        size = 10 + (nargs * 10);
        
-       p = buf = g_malloc (size);
+       sigbuffer_init (&buf, 32);
 
        /* Encode calling convention */
        /* Change Any to Standard */
@@ -2675,26 +2666,33 @@ mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigH
                helper->call_conv &= 0x20;
 
        if (helper->call_conv == 0) { /* Unmanaged */
-               *p = helper->unmanaged_call_conv - 1;
+               idx = helper->unmanaged_call_conv - 1;
        } else {
                /* Managed */
-               *p = helper->call_conv & 0x60; /* has_this + explicit_this */
+               idx = helper->call_conv & 0x60; /* has_this + explicit_this */
                if (helper->call_conv & 0x02) /* varargs */
-                       *p += 0x05;
+                       idx += 0x05;
        }
 
-       p++;
-       mono_metadata_encode_value (nargs, p, &p);
-       encode_reflection_type (assembly, helper->return_type, p, &p);
+       sigbuffer_add_byte (&buf, idx);
+       sigbuffer_add_value (&buf, nargs);
+       encode_reflection_type (assembly, helper->return_type, &buf);
        for (i = 0; i < nargs; ++i) {
-               MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
-               encode_reflection_type (assembly, pt, p, &p);
+               MonoArray *modreqs = NULL;
+               MonoArray *modopts = NULL;
+               MonoReflectionType *pt;
+
+               if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
+                       modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
+               if (helper->modopts && (i < mono_array_length (helper->modopts)))
+                       modopts = mono_array_get (helper->modopts, MonoArray*, i);
+
+               encode_custom_modifiers (assembly, modreqs, modopts, &buf);
+               pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
+               encode_reflection_type (assembly, pt, &buf);
        }
-       /* store length */
-       g_assert (p - buf < size);
-       mono_metadata_encode_value (p-buf, b, &b);
-       idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
-       g_free (buf);
+       idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+       sigbuffer_free (&buf);
 
        return idx;
 }
@@ -3094,7 +3092,7 @@ mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, Mo
        g_free (path);
        mono_metadata_encode_value (20, b, &b);
        values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
-       mono_image_add_stream_data (&assembly->blob, hash, 20);
+       mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
        table->next_idx ++;
 }
 
@@ -3416,7 +3414,7 @@ build_compressed_metadata (MonoDynamicImage *assembly)
        heapt_size &= ~3;
        meta_size += heapt_size;
        meta->raw_metadata = g_malloc0 (meta_size);
-       p = meta->raw_metadata;
+       p = (unsigned char*)meta->raw_metadata;
        /* the metadata signature */
        *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
        /* version numbers and 4 bytes reserved */
@@ -3451,7 +3449,7 @@ build_compressed_metadata (MonoDynamicImage *assembly)
                table_offset += GUINT32_FROM_LE (*int32val);
                table_offset += 3; table_offset &= ~3;
                p += 8;
-               strcpy (p, stream_desc [i].name);
+               strcpy ((char*)p, stream_desc [i].name);
                p += strlen (stream_desc [i].name) + 1;
                align_pointer (meta->raw_metadata, p);
        }
@@ -3459,7 +3457,7 @@ build_compressed_metadata (MonoDynamicImage *assembly)
         * now copy the data, the table stream header and contents goes first.
         */
        g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
-       p = meta->raw_metadata + assembly->tstream.offset;
+       p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
        int32val = (guint32*)p;
        *int32val = GUINT32_TO_LE (0); /* reserved */
        p += 4;
@@ -3524,7 +3522,7 @@ build_compressed_metadata (MonoDynamicImage *assembly)
                        continue;
                if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
                        g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
-               meta->tables [i].base = p;
+               meta->tables [i].base = (char*)p;
                for (row = 1; row <= meta->tables [i].rows; ++row) {
                        values = assembly->tables [i].values + row * assembly->tables [i].columns;
                        for (col = 0; col < assembly->tables [i].columns; ++col) {
@@ -3582,7 +3580,7 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
 
        for (i = 0; i < ilgen->num_token_fixups; ++i) {
                iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
-               target = assembly->code.data + code_idx + iltoken->code_pos;
+               target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
                switch (target [3]) {
                case MONO_TABLE_FIELD:
                        if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
@@ -3633,7 +3631,8 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
                                MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
                                g_assert (f->generic_info);
                                continue;
-                       } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
+                       } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
+                                       !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
                                continue;
                        } else {
                                g_assert_not_reached ();
@@ -3735,7 +3734,7 @@ assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assemb
                mono_sha1_get_digest_from_file (name, hash);
                mono_metadata_encode_value (20, b, &b);
                values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
-               mono_image_add_stream_data (&assembly->blob, hash, 20);
+               mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
                g_free (name);
                idx = table->next_idx++;
                rsrc->offset = 0;
@@ -3813,10 +3812,14 @@ load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
        len = mono_array_length (pkey);
        mono_metadata_encode_value (len, b, &b);
        token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
-       mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
+       mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
+
+       assembly->public_key = g_malloc (len);
+       memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
+       assembly->public_key_len = len;
 
        /* Special case: check for ECMA key (16 bytes) */
-       if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, guint8, 0), len)) {
+       if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
                /* In this case we must reserve 128 bytes (1024 bits) for the signature */
                assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
        } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
@@ -4184,12 +4187,19 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, Mon
  * Get a token to insert in the IL code stream for the given MemberInfo.
  * @obj can be one of:
  *     ConstructorBuilder
- *     MethodBuilder
+ *      EnumBuilder
  *     FieldBuilder
+ *      GenericTypeParameterBuilder
+ *     MethodBuilder
+ *      MonoArrayMethod
  *     MonoCMethod
  *     MonoMethod
  *     MonoField
+ *      MonoGenericClass
+ *      MonoGenericMethod
+ *      MonoGenericCMethod
  *     MonoType
+ *      SignatureHelperxo
  *     TypeBuilder
  */
 guint32
@@ -4201,16 +4211,18 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean c
        klass = obj->vtable->klass;
        if (strcmp (klass->name, "MethodBuilder") == 0) {
                MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
+               MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
 
-               if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
+               if (tb->module->dynamic_image == assembly && !tb->generic_params)
                        token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
                else
                        token = mono_image_get_methodbuilder_token (assembly, mb);
                /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
        } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
                MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
+               MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
 
-               if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
+               if (tb->module->dynamic_image == assembly && !tb->generic_params)
                        token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
                else
                        token = mono_image_get_ctorbuilder_token (assembly, mb);
@@ -4226,8 +4238,12 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean c
        } else if (strcmp (klass->name, "TypeBuilder") == 0) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
                token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
-       } else if (strcmp (klass->name, "MonoType") == 0 ||
-                strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
+       } else if (strcmp (klass->name, "MonoType") == 0) {
+               MonoReflectionType *tb = (MonoReflectionType *)obj;
+               MonoClass *mc = mono_class_from_mono_type (tb->type);
+               token = mono_metadata_token_from_dor (
+                       mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
+       } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
                MonoReflectionType *tb = (MonoReflectionType *)obj;
                token = mono_metadata_token_from_dor (
                        mono_image_typedef_or_ref (assembly, tb->type));
@@ -4325,7 +4341,9 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c
 #else
        image = g_new0 (MonoDynamicImage, 1);
 #endif
-
+       
+       mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
+       
        /*g_print ("created image %p\n", image);*/
        /* keep in sync with image.c */
        image->image.name = assembly_name;
@@ -4357,7 +4375,7 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c
        mono_image_add_stream_data (&image->us, "", 1);
        add_to_blob_cached (image, (char*) "", 1, NULL, 0);
        /* import tables... */
-       mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
+       mono_image_add_stream_data (&image->code, (char*)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 */
        image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
@@ -4378,6 +4396,8 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c
        image->save = assembly->save;
        image->pe_kind = 0x1; /* ILOnly */
        image->machine = 0x14c; /* I386 */
+       
+       mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
 
        return image;
 }
@@ -4407,6 +4427,8 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
        assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
 #endif
 
+       mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
+       
        assembly->assembly.ref_count = 1;
        assembly->assembly.dynamic = TRUE;
        assembly->assembly.corlib_internal = assemblyb->corlib_internal;
@@ -4448,6 +4470,9 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
        mono_domain_assemblies_unlock (domain);
 
        register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
+       
+       mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
+       
        mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
 }
 
@@ -4675,7 +4700,7 @@ assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssembly
 
        resource_tree_encode (tree, p, p, &p);
 
-       g_assert (p - buf < size);
+       g_assert (p - buf <= size);
 
        assembly->win32_res = g_malloc (p - buf);
        assembly->win32_res_size = p - buf;
@@ -4779,7 +4804,7 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
        
        /* The DOS header and stub */
        g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
-       mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
+       mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
 
        /* the dotnet header */
        header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
@@ -4928,7 +4953,7 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
        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);
+       p = (guchar*)(assembly->code.data + assembly->ilt_offset);
        value = (assembly->text_rva + assembly->imp_names_offset);
        *p++ = (value) & 0xff;
        *p++ = (value >> 8) & (0xff);
@@ -4999,7 +5024,7 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
                switch (i) {
                case MONO_SECTION_TEXT:
                        /* patch entry point */
-                       p = (assembly->code.data + 2);
+                       p = (guchar*)(assembly->code.data + 2);
                        value = (virtual_base + assembly->text_rva + assembly->iat_offset);
                        *p++ = (value) & 0xff;
                        *p++ = (value >> 8) & 0xff;
@@ -5070,7 +5095,7 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
 }
 
 MonoReflectionModule *
-mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
+mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
 {
        char *name;
        MonoImage *image;
@@ -5078,6 +5103,7 @@ mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
        MonoDynamicAssembly *assembly;
        guint32 module_count;
        MonoImage **new_modules;
+       gboolean *new_modules_loaded;
        
        name = mono_string_to_utf8 (fileName);
 
@@ -5099,14 +5125,19 @@ mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
 
        module_count = image->assembly->image->module_count;
        new_modules = g_new0 (MonoImage *, module_count + 1);
+       new_modules_loaded = g_new0 (gboolean, module_count + 1);
 
        if (image->assembly->image->modules)
                memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
+       if (image->assembly->image->modules_loaded)
+               memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
        new_modules [module_count] = image;
+       new_modules_loaded [module_count] = TRUE;
        mono_image_addref (image);
 
        g_free (image->assembly->image->modules);
        image->assembly->image->modules = new_modules;
+       image->assembly->image->modules_loaded = new_modules_loaded;
        image->assembly->image->module_count ++;
 
        mono_assembly_load_references (image, &status);
@@ -5159,9 +5190,7 @@ reflected_hash (gconstpointer a) {
         mono_domain_unlock (domain); \
        } while (0)
 
-#if HAVE_BOEHM_GC
-#define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
-#elif HAVE_SGEN_GC
+#ifndef HAVE_NULL_GC
 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
 #else
 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
@@ -5383,13 +5412,16 @@ 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->inst->type_argc != t2->data.generic_class->inst->type_argc)
+               MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
+               MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
+               if (i1->type_argc != i2->type_argc)
                        return FALSE;
                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->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]))
+               /* FIXME: we should probably just compare the instance pointers directly.  */
+               for (i = 0; i < i1->type_argc; ++i) {
+                       if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
                                return FALSE;
                }
                return TRUE;
@@ -5423,7 +5455,7 @@ mymono_metadata_type_hash (MonoType *t1)
                return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
        case MONO_TYPE_GENERICINST: {
                int i;
-               MonoGenericInst *inst = t1->data.generic_class->inst;
+               MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
                hash += g_str_hash (t1->data.generic_class->container_class->name);
                hash *= 13;
                for (i = 0; i < inst->type_argc; ++i) {
@@ -5462,10 +5494,9 @@ mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
 #endif
 
        res->type.type = geninst;
-       if (gklass->wastypebuilder && gklass->reflection_info)
-               MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
-       else
-               MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
+       g_assert (gklass->reflection_info);
+       g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
+       MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
 
        return res;
 }
@@ -5520,7 +5551,8 @@ mono_type_get_object (MonoDomain *domain, MonoType *type)
                mono_domain_unlock (domain);
                return res;
        }
-       if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
+       /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
+       if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
                res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
                mono_g_hash_table_insert (domain->type_hash, type, res);
                mono_domain_unlock (domain);
@@ -5571,14 +5603,12 @@ mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refcl
        static MonoClass *System_Reflection_MonoCMethod = NULL;
        static MonoClass *System_Reflection_MonoGenericMethod = NULL;
        static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
-       const char *cname;
        MonoClass *klass;
        MonoReflectionMethod *ret;
 
        if (method->is_inflated) {
                MonoReflectionGenericMethod *gret;
 
-               method = mono_get_inflated_method (method);
                refclass = method->klass;
                CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
                if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
@@ -5613,7 +5643,6 @@ mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refcl
        }
        ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
        ret->method = method;
-       MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
        MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
        CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
 }
@@ -5631,11 +5660,12 @@ MonoReflectionField*
 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
 {
        MonoReflectionField *res;
-       MonoClass *oklass;
+       static MonoClass *monofield_klass;
 
        CHECK_OBJECT (MonoReflectionField *, field, klass);
-       oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
-       res = (MonoReflectionField *)mono_object_new (domain, oklass);
+       if (!monofield_klass)
+               monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
+       res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
        res->klass = klass;
        res->field = field;
        MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
@@ -5660,11 +5690,12 @@ MonoReflectionProperty*
 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
 {
        MonoReflectionProperty *res;
-       MonoClass *oklass;
+       static MonoClass *monoproperty_klass;
 
        CHECK_OBJECT (MonoReflectionProperty *, property, klass);
-       oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
-       res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
+       if (!monoproperty_klass)
+               monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
+       res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
        res->klass = klass;
        res->property = property;
        CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
@@ -5683,16 +5714,61 @@ MonoReflectionEvent*
 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
 {
        MonoReflectionEvent *res;
-       MonoClass *oklass;
+       static MonoClass *monoevent_klass;
 
        CHECK_OBJECT (MonoReflectionEvent *, event, klass);
-       oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
-       res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
+       if (!monoevent_klass)
+               monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
+       res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
        res->klass = klass;
        res->event = event;
        CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
 }
 
+/**
+ * mono_get_reflection_missing_object:
+ * @domain: Domain where the object lives
+ *
+ * Returns the System.Reflection.Missing.Value singleton object
+ * (of type System.Reflection.Missing).
+ *
+ * Used as the value for ParameterInfo.DefaultValue when Optional
+ * is present
+ */
+static MonoObject *
+mono_get_reflection_missing_object (MonoDomain *domain)
+{
+       MonoObject *obj;
+       static MonoClassField *missing_value_field = NULL;
+       
+       if (!missing_value_field) {
+               MonoClass *missing_klass;
+               missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
+               mono_class_init (missing_klass);
+               missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
+               g_assert (missing_value_field);
+       }
+       obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
+       g_assert (obj);
+       return obj;
+}
+
+static MonoObject*
+get_dbnull (MonoDomain *domain, MonoObject **dbnull)
+{
+       if (!*dbnull)
+               *dbnull = mono_get_dbnull_object (domain);
+       return *dbnull;
+}
+
+static MonoObject*
+get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
+{
+       if (!*reflection_missing)
+               *reflection_missing = mono_get_reflection_missing_object (domain);
+       return *reflection_missing;
+}
+
 /*
  * mono_param_get_objects:
  * @domain: an app domain
@@ -5711,7 +5787,8 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
        char **names, **blobs = NULL;
        guint32 *types = NULL;
        MonoType *type = NULL;
-       MonoObject *dbnull = mono_get_dbnull_object (domain);
+       MonoObject *dbnull = NULL;
+       MonoObject *missing = NULL;
        MonoMarshalSpec **mspecs;
        MonoMethodSignature *sig;
        int i;
@@ -5746,7 +5823,10 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
                param->AttrsImpl = sig->params [i]->attrs;
 
                if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
-                       MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
+                       if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
+                               MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
+                       else
+                               MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
                } else {
 
                        if (!blobs) {
@@ -5773,8 +5853,12 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
                        MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
 
                        /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
-                       if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) 
-                               MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
+                       if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
+                               if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
+                                       MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
+                               else
+                                       MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
+                       }
                        
                }
 
@@ -5895,17 +5979,25 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
        return ret;
 }
 
+/**
+ * mono_get_dbnull_object:
+ * @domain: Domain where the object lives
+ *
+ * Returns the System.DBNull.Value singleton object
+ *
+ * Used as the value for ParameterInfo.DefaultValue 
+ */
 MonoObject *
 mono_get_dbnull_object (MonoDomain *domain)
 {
        MonoObject *obj;
-       MonoClass *klass;
        static MonoClassField *dbnull_value_field = NULL;
        
        if (!dbnull_value_field) {
-               klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
-               mono_class_init (klass);
-               dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
+               MonoClass *dbnull_klass;
+               dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
+               mono_class_init (dbnull_klass);
+               dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
                g_assert (dbnull_value_field);
        }
        obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
@@ -5913,7 +6005,6 @@ mono_get_dbnull_object (MonoDomain *domain)
        return obj;
 }
 
-
 static void
 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
 {
@@ -6072,7 +6163,7 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
                                len = (p - start + 1);
                                if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
                                        len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
-                               g_strlcpy (assembly->public_key_token, start, len);
+                               g_strlcpy ((char*)assembly->public_key_token, start, len);
                        }
                } else {
                        while (*p && *p != ',')
@@ -6115,6 +6206,7 @@ _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
 
        start = p = w = name;
 
+       //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
        memset (&info->assembly, 0, sizeof (MonoAssemblyName));
        info->name = info->name_space = NULL;
        info->nested = NULL;
@@ -6315,6 +6407,7 @@ _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image,
 {
        gboolean type_resolve = FALSE;
        MonoType *type;
+       MonoImage *rootimage = image;
 
        if (info->assembly.name) {
                MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
@@ -6329,17 +6422,17 @@ _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image,
                image = mono_defaults.corlib;
        }
 
-       type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
+       type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
        if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
                image = mono_defaults.corlib;
-               type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
+               type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
        }
 
        return type;
 }
 
 static MonoType*
-mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
+mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
 {
        MonoClass *klass;
        GList *mod;
@@ -6388,7 +6481,7 @@ mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gb
                for (i = 0; i < info->type_arguments->len; i++) {
                        MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
 
-                       type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
+                       type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
                        if (!type_args [i]) {
                                g_free (type_args);
                                return NULL;
@@ -6400,10 +6493,9 @@ mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gb
                instance = mono_reflection_bind_generic_parameters (
                        the_type, info->type_arguments->len, type_args);
 
-               if (!instance) {
-                       g_free (type_args);
+               g_free (type_args);
+               if (!instance)
                        return NULL;
-               }
 
                klass = mono_class_from_mono_type (instance);
        }
@@ -6435,14 +6527,55 @@ mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gb
  */
 
 MonoType*
-mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
+mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
+       return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
+}
+
+static MonoType*
+mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
+{
+       MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
+       MonoType *type;
+       int i;
+
+       g_assert (assembly->dynamic);
+
+       /* Enumerate all modules */
+
+       type = NULL;
+       if (abuilder->modules) {
+               for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
+                       MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
+                       type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
+                       if (type)
+                               break;
+               }
+       }
+
+       if (!type && abuilder->loaded_modules) {
+               for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
+                       MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
+                       type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
+                       if (type)
+                               break;
+               }
+       }
+
+       return type;
+}
+       
+MonoType*
+mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
 {
        MonoType *type;
        MonoReflectionAssembly *assembly;
        GString *fullName;
        GList *mod;
 
-       type = mono_reflection_get_type_internal (image, info, ignorecase);
+       if (image && image->dynamic)
+               type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
+       else
+               type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
        if (type)
                return type;
        if (!mono_domain_has_type_resolve (mono_domain_get ()))
@@ -6466,40 +6599,18 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
 
        assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
        if (assembly) {
-               if (assembly->assembly->dynamic) {
-                       /* Enumerate all modules */
-                       MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
-                       int i;
-
-                       type = NULL;
-                       if (abuilder->modules) {
-                               for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
-                                       MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
-                                       type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
-                                       if (type)
-                                               break;
-                               }
-                       }
-
-                       if (!type && abuilder->loaded_modules) {
-                               for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
-                                       MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
-                                       type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
-                                       if (type)
-                                               break;
-                               }
-                       }
-               }
+               if (assembly->assembly->dynamic)
+                       type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
                else
-                       type = mono_reflection_get_type_internal (assembly->assembly->image, 
+                       type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
                                                                                                          info, ignorecase);
        }
        g_string_free (fullName, TRUE);
        return type;
 }
 
-static void
-free_type_info (MonoTypeNameParse *info)
+void
+mono_reflection_free_type_info (MonoTypeNameParse *info)
 {
        g_list_free (info->modifiers);
        g_list_free (info->nested);
@@ -6510,7 +6621,9 @@ free_type_info (MonoTypeNameParse *info)
                for (i = 0; i < info->type_arguments->len; i++) {
                        MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
 
-                       free_type_info (subinfo);
+                       mono_reflection_free_type_info (subinfo);
+                       /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
+                       g_free (subinfo);
                }
 
                g_ptr_array_free (info->type_arguments, TRUE);
@@ -6543,7 +6656,7 @@ mono_reflection_type_from_name (char *name, MonoImage *image)
        }
 
        g_free (tmp);
-       free_type_info (&info);
+       mono_reflection_free_type_info (&info);
        return type;
 }
 
@@ -6571,7 +6684,9 @@ mono_reflection_get_token (MonoObject *obj)
                token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
        } else if (strcmp (klass->name, "FieldBuilder") == 0) {
                MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
-               token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
+
+               /* Call mono_image_create_token so the object gets added to the tokens hash table */
+               token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE);
        } else if (strcmp (klass->name, "TypeBuilder") == 0) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
                token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
@@ -6664,7 +6779,6 @@ handle_enum:
        case MONO_TYPE_U: /* error out instead? this should probably not happen */
        case MONO_TYPE_I:
 #endif
-       case MONO_TYPE_R8:
        case MONO_TYPE_U8:
        case MONO_TYPE_I8: {
                guint64 *val = g_malloc (sizeof (guint64));
@@ -6672,6 +6786,12 @@ handle_enum:
                *end = p + 8;
                return val;
        }
+       case MONO_TYPE_R8: {
+               double *val = g_malloc (sizeof (double));
+               readr8 (p, val);
+               *end = p + 8;
+               return val;
+       }
        case MONO_TYPE_VALUETYPE:
                if (t->data.klass->enumtype) {
                        type = t->data.klass->enum_basetype->type;
@@ -6725,6 +6845,9 @@ handle_type:
                        int etype = *p;
                        p ++;
 
+                       if (etype == 0x51)
+                               /* See Partition II, Appendix B3 */
+                               etype = MONO_TYPE_OBJECT;
                        type = MONO_TYPE_SZARRAY;
                        simple_type.type = etype;
                        tklass = mono_class_from_mono_type (&simple_type);
@@ -6796,6 +6919,13 @@ handle_type:
                                }
                                break;
                        case MONO_TYPE_R8:
+                               for (i = 0; i < alen; i++) {
+                                       double val;
+                                       readr8 (p, &val);
+                                       mono_array_set (arr, double, i, val);
+                                       p += 8;
+                               }
+                               break;
                        case MONO_TYPE_U8:
                        case MONO_TYPE_I8:
                                for (i = 0; i < alen; i++) {
@@ -7035,7 +7165,6 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat
 {
        MonoArray *typedargs, *namedargs;
        MonoClass *attrklass;
-       static MonoClass *klass;
        static MonoMethod *ctor;
        MonoDomain *domain;
        MonoObject *attr;
@@ -7045,16 +7174,14 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat
        void *params [3];
 
        mono_class_init (method->klass);
-       
-       if (!klass)
-               klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
+
        if (!ctor)
-               ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
-       
+               ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
+
        domain = mono_domain_get ();
        if (len == 0) {
                /* This is for Attributes with no parameters */
-               attr = mono_object_new (domain, klass);
+               attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
                params [0] = mono_method_get_object (domain, method, NULL);
                params [1] = params [2] = NULL;
                mono_runtime_invoke (method, attr, params, NULL);
@@ -7141,7 +7268,7 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat
                }
                g_free (name);
        }
-       attr = mono_object_new (domain, klass);
+       attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
        params [0] = mono_method_get_object (domain, method, NULL);
        params [1] = typedargs;
        params [2] = namedargs;
@@ -7153,12 +7280,10 @@ MonoArray*
 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
 {
        MonoArray *result;
-       MonoClass *klass;
        MonoObject *attr;
        int i;
 
-       klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
-       result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
+       result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
        for (i = 0; i < cinfo->num_attrs; ++i) {
                attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
                mono_array_setref (result, i, attr);
@@ -7171,7 +7296,6 @@ mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_
 {
        MonoArray *result;
        MonoObject *attr;
-       MonoClass *klass;
        int i, n;
 
        n = 0;
@@ -7180,8 +7304,7 @@ mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_
                        n ++;
        }
 
-       klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
-       result = mono_array_new (mono_domain_get (), klass, n);
+       result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
        n = 0;
        for (i = 0; i < cinfo->num_attrs; ++i) {
                if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
@@ -7197,14 +7320,10 @@ static MonoArray*
 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
 {
        MonoArray *result;
-       static MonoClass *klass;
        MonoObject *attr;
        int i;
-
-       if (!klass)
-               klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
        
-       result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
+       result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
        for (i = 0; i < cinfo->num_attrs; ++i) {
                attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
                mono_array_setref (result, i, attr);
@@ -7212,6 +7331,11 @@ mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
        return result;
 }
 
+/**
+ * mono_custom_attrs_from_index:
+ *
+ * Returns: NULL if no attributes are found or if a loading error occurs.
+ */
 MonoCustomAttrInfo*
 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
 {
@@ -7255,8 +7379,12 @@ mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
                        break;
                }
                ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
-               if (!ainfo->attrs [i].ctor)
-                       g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
+               if (!ainfo->attrs [i].ctor) {
+                       g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
+                       g_list_free (list);
+                       g_free (ainfo);
+                       return NULL;
+               }
                data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
                ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
                ainfo->attrs [i].data = (guchar*)data;
@@ -7271,8 +7399,17 @@ mono_custom_attrs_from_method (MonoMethod *method)
 {
        MonoCustomAttrInfo *cinfo;
        guint32 idx;
+
+       /*
+        * An instantiated method has the same cattrs as the generic method definition.
+        *
+        * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
+        *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
+        */
+       if (method->is_inflated)
+               method = ((MonoMethodInflated *) method)->declaring;
        
-       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
+       if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
                return cinfo;
        idx = mono_method_get_index (method);
        idx <<= MONO_CUSTOM_ATTR_BITS;
@@ -7285,8 +7422,11 @@ mono_custom_attrs_from_class (MonoClass *klass)
 {
        MonoCustomAttrInfo *cinfo;
        guint32 idx;
+
+       if (klass->generic_class)
+               klass = klass->generic_class->container_class;
        
-       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
+       if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
                return cinfo;
        idx = mono_metadata_token_index (klass->type_token);
        idx <<= MONO_CUSTOM_ATTR_BITS;
@@ -7300,7 +7440,7 @@ mono_custom_attrs_from_assembly (MonoAssembly *assembly)
        MonoCustomAttrInfo *cinfo;
        guint32 idx;
        
-       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
+       if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
                return cinfo;
        idx = 1; /* there is only one assembly */
        idx <<= MONO_CUSTOM_ATTR_BITS;
@@ -7314,7 +7454,7 @@ mono_custom_attrs_from_module (MonoImage *image)
        MonoCustomAttrInfo *cinfo;
        guint32 idx;
        
-       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
+       if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
                return cinfo;
        idx = 1; /* there is only one module */
        idx <<= MONO_CUSTOM_ATTR_BITS;
@@ -7328,7 +7468,7 @@ mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
        MonoCustomAttrInfo *cinfo;
        guint32 idx;
        
-       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
+       if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
                return cinfo;
        idx = find_property_index (klass, property);
        idx <<= MONO_CUSTOM_ATTR_BITS;
@@ -7342,7 +7482,7 @@ mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
        MonoCustomAttrInfo *cinfo;
        guint32 idx;
        
-       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
+       if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
                return cinfo;
        idx = find_event_index (klass, event);
        idx <<= MONO_CUSTOM_ATTR_BITS;
@@ -7356,7 +7496,7 @@ mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
        MonoCustomAttrInfo *cinfo;
        guint32 idx;
        
-       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
+       if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
                return cinfo;
        idx = find_field_index (klass, field);
        idx <<= MONO_CUSTOM_ATTR_BITS;
@@ -7373,11 +7513,29 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
        MonoImage *image;
        MonoReflectionMethodAux *aux;
 
+       /*
+        * An instantiated method has the same cattrs as the generic method definition.
+        *
+        * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
+        *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
+        */
+       if (method->is_inflated)
+               method = ((MonoMethodInflated *) method)->declaring;
+
        if (method->klass->image->dynamic) {
+               MonoCustomAttrInfo *res, *ainfo;
+               int size;
+
                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];
+
+               /* Need to copy since it will be freed later */
+               ainfo = aux->param_cattr [param];
+               size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
+               res = g_malloc0 (size);
+               memcpy (res, ainfo, size);
+               return res;
        }
 
        image = method->klass->image;
@@ -7483,8 +7641,8 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj)
                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);
+               MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
+               cinfo = mono_custom_attrs_from_method (rmethod->method);
        } else if (strcmp ("ParameterInfo", klass->name) == 0) {
                MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
                MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
@@ -7507,6 +7665,9 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj)
        } else if (strcmp ("FieldBuilder", klass->name) == 0) {
                MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
                cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
+       } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
+               MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
+               cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
        } else { /* handle other types here... */
                g_error ("get custom attrs not yet supported for %s", klass->name);
        }
@@ -7520,7 +7681,8 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj)
  *
  * Return an array with all the custom attributes defined of the
  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
- * of that type are returned. The objects are fully build.
+ * of that type are returned. The objects are fully build. Return NULL if a loading error
+ * occurs.
  */
 MonoArray*
 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
@@ -7537,9 +7699,9 @@ mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass
                if (!cinfo->cached)
                        mono_custom_attrs_free (cinfo);
        } else {
-               MonoClass *klass;
-               klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
-               result = mono_array_new (mono_domain_get (), klass, 0);
+               if (mono_loader_get_last_error ())
+                       return NULL;
+               result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
        }
 
        return result;
@@ -7550,7 +7712,8 @@ mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass
  * @obj: a reflection object handle
  *
  * Return an array with all the custom attributes defined of the
- * reflection handle @obj. The objects are fully build.
+ * reflection handle @obj. The objects are fully build. Return NULL if a loading error
+ * occurs.
  */
 MonoArray*
 mono_reflection_get_custom_attrs (MonoObject *obj)
@@ -7577,15 +7740,37 @@ mono_reflection_get_custom_attrs_data (MonoObject *obj)
                result = mono_custom_attrs_data_construct (cinfo);
                if (!cinfo->cached)
                        mono_custom_attrs_free (cinfo);
-       } else {
-               MonoClass *klass;
-               klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
-               result = mono_array_new (mono_domain_get (), klass, 0);
-       }
+       } else
+               result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
 
        return result;
 }
 
+static MonoReflectionType*
+mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
+{
+        MonoMethod *method_get_underlying_system_type;
+
+        method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
+                                                                            mono_class_get_method_from_name (mono_object_class (t),
+                                                                                                             "get_UnderlyingSystemType",
+                                                                                                             0));
+        return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
+}
+
+static MonoType*
+mono_reflection_type_get_handle (MonoReflectionType* t)
+{
+        if (t->type)
+            return t->type;
+
+        t = mono_reflection_type_get_underlying_system_type (t);
+        if (t)
+            return t->type;
+
+        return NULL;
+}
+
 /**
  * LOCKING: Assumes the loader lock is held.
  */
@@ -7601,7 +7786,7 @@ parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
        sig->sentinelpos = -1; /* FIXME */
        for (i = 0; i < count; ++i) {
                MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
-               sig->params [i] = pt->type;
+               sig->params [i] = mono_reflection_type_get_handle (pt);
        }
        return sig;
 }
@@ -7723,9 +7908,23 @@ handle_enum:
                swap_with_size (p, argval, 4, 1);
                p += 4;
                break;
+       case MONO_TYPE_R8:
+#if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
+               p [0] = argval [4];
+               p [1] = argval [5];
+               p [2] = argval [6];
+               p [3] = argval [7];
+               p [4] = argval [0];
+               p [5] = argval [1];
+               p [6] = argval [2];
+               p [7] = argval [3];
+#else
+               swap_with_size (p, argval, 8, 1);
+#endif
+               p += 8;
+               break;
        case MONO_TYPE_U8:
        case MONO_TYPE_I8:
-       case MONO_TYPE_R8:
                swap_with_size (p, argval, 8, 1);
                p += 8;
                break;
@@ -7770,8 +7969,18 @@ handle_enum:
                }
                k = mono_object_class (arg);
                if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
-                               (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
-                       g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
+                        (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
+                        MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
+                        MonoClass *rtc;
+                        
+                        if (rt && (rtc = mono_object_class (rt)) &&
+                                   (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
+                                    !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
+                                arg = (MonoObject *) rt;
+                                k = rtc;
+                        } else
+                                g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
+                }
 handle_type:
                str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
                slen = strlen (str);
@@ -7827,7 +8036,7 @@ handle_type:
                        }
                } else {
                        for (i = 0; i < len; ++i) {
-                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
+                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
                        }
                }
                break;
@@ -7861,10 +8070,14 @@ handle_type:
                        *p++ = 0x0E;
                        goto handle_enum;
                } else if (klass->rank == 1) {
-                       simple_type = MONO_TYPE_SZARRAY;
                        *p++ = 0x1D;
-                       *p++ = klass->element_class->byval_arg.type;
-                       goto handle_enum;
+                       if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
+                               /* See Partition II, Appendix B3 */
+                               *p++ = 0x51;
+                       else
+                               *p++ = klass->element_class->byval_arg.type;
+                       encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
+                       break;
                } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
                        *p++ = simple_type = klass->byval_arg.type;
                        goto handle_enum;
@@ -8114,6 +8327,8 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
        klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
        klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
        klass->flags = tb->attrs;
+       
+       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
 
        klass->element_class = klass;
 
@@ -8161,6 +8376,8 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
 
        /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
 
+       mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+       
        mono_loader_unlock ();
 }
 
@@ -8182,7 +8399,7 @@ mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
                return;
 
        tb->generic_container = g_new0 (MonoGenericContainer, 1);
-       tb->generic_container->klass = klass;
+       tb->generic_container->owner.klass = klass;
 }
 
 /*
@@ -8206,7 +8423,7 @@ mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
        if (klass->generic_container || (count == 0))
                return;
 
-       g_assert (tb->generic_container && (tb->generic_container->klass == klass));
+       g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
 
        klass->generic_container = tb->generic_container;
 
@@ -8247,6 +8464,11 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
 
                fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
 
+               if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
+                       mono_loader_unlock ();
+                       return;
+               }
+
                klass->enum_basetype = fb->type->type;
                klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
                if (!klass->element_class)
@@ -8373,8 +8595,6 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
        gboolean dynamic;
        int i;
 
-       g_assert (!klass->generic_class);
-
        /*
         * Methods created using a MethodBuilder should have their memory allocated
         * inside the image mempool, while dynamic methods should have their memory
@@ -8383,6 +8603,9 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
        dynamic = rmb->refs != NULL;
        mp = dynamic ? NULL : klass->image->mempool;
 
+       if (!dynamic)
+               g_assert (!klass->generic_class);
+
        mono_loader_lock ();
 
        if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
@@ -8395,10 +8618,11 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
 
        pm = (MonoMethodNormal*)m;
 
+       m->dynamic = dynamic;
        m->slot = -1;
        m->flags = rmb->attrs;
        m->iflags = rmb->iattrs;
-       m->name = dynamic ? mono_string_to_utf8 (rmb->name) : mono_string_to_utf8_mp (mp, rmb->name);
+       m->name = mp_string_to_utf8 (mp, rmb->name);
        m->klass = klass;
        m->signature = sig;
        m->skip_visibility = rmb->skip_visibility;
@@ -8489,20 +8713,20 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                m->generic_container = container = rmb->generic_container;
                container->type_argc = count;
                container->type_params = g_new0 (MonoGenericParam, count);
+               container->owner.method = m;
 
                for (i = 0; i < count; i++) {
                        MonoReflectionGenericParam *gp =
                                mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
 
                        container->type_params [i] = *gp->type.type->data.generic_param;
-                       container->type_params [i].method = m;
                }
 
                if (klass->generic_container) {
                        container->parent = klass->generic_container;
                        container->context.class_inst = klass->generic_container->context.class_inst;
                }
-               container->context.gmethod = mono_get_shared_generic_method (container);
+               container->context.method_inst = mono_get_shared_generic_inst (container);
        }
 
        if (rmb->refs) {
@@ -8531,7 +8755,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                                if ((i > 0) && (pb->attrs)) {
                                        /* Make a copy since it might point to a shared type structure */
                                        /* FIXME: Alloc this from a mempool */
-                                       m->signature->params [i - 1] = g_memdup (m->signature->params [i - 1], sizeof (MonoType) + ((m->signature->params [i - 1]->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)));
+                                       m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]);
                                        m->signature->params [i - 1]->attrs = pb->attrs;
                                }
 
@@ -8557,7 +8781,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                                }
 
                                if (pb->name)
-                                       method_aux->param_names [i] = dynamic ? mono_string_to_utf8 (pb->name) : mono_string_to_utf8_mp (mp, pb->name);
+                                       method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
                                if (pb->cattrs) {
                                        if (!method_aux->param_cattr)
                                                method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
@@ -8610,7 +8834,8 @@ ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
        mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
        mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
 
-       if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
+       /* If we are in a generic class, we might be called multiple times from inflate_method */
+       if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
                /* ilgen is no longer needed */
                mb->ilgen = NULL;
        }
@@ -8633,7 +8858,8 @@ methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
        mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
        mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
 
-       if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
+       /* If we are in a generic class, we might be called multiple times from inflate_method */
+       if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
                /* ilgen is no longer needed */
                mb->ilgen = NULL;
        }
@@ -8684,11 +8910,9 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
 {
        MonoClass *klass;
        MonoReflectionTypeBuilder *tb = NULL;
-       MonoGenericClass *gclass, *cached;
        gboolean is_dynamic = FALSE;
        MonoDomain *domain;
-       MonoType *geninst;
-       int i;
+       MonoClass *geninst;
 
        mono_loader_lock ();
 
@@ -8700,11 +8924,8 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
                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;
 
+               tb = rgi->generic_type;
                is_dynamic = TRUE;
        }
 
@@ -8724,171 +8945,37 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
                is_dynamic = TRUE;
        }
 
-       if (is_dynamic) {
-               MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
-               MonoInflatedGenericClass *igclass = &dgclass->generic_class;
-               gclass = &igclass->generic_class;
-               gclass->is_dynamic = TRUE;
-               gclass->is_inflated = TRUE;
-       } else {
-               MonoInflatedGenericClass *igclass = g_new0 (MonoInflatedGenericClass, 1);
-               gclass = &igclass->generic_class;
-               gclass->is_inflated = TRUE;
-       }
-
-       gclass->inst = g_new0 (MonoGenericInst, 1);
-
-       gclass->inst->type_argc = type_argc;
-       gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
-       gclass->inst->is_reference = 1;
-
-       for (i = 0; i < gclass->inst->type_argc; ++i) {
-               MonoType *t = dup_type (types [i]);
-
-               if (!gclass->inst->is_open)
-                       gclass->inst->is_open = mono_class_is_open_constructed_type (t);
-               if (gclass->inst->is_reference)
-                       gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
-               gclass->inst->type_argv [i] = t;
-       }
-
-       gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
-
-       gclass->container_class = klass;
-
-       geninst = g_new0 (MonoType, 1);
-       geninst->type = MONO_TYPE_GENERICINST;
-
-       cached = mono_metadata_lookup_generic_class (gclass);
-       if (cached) {
-               g_free (gclass);
-               mono_loader_unlock ();
-               geninst->data.generic_class = cached;
-               return geninst;
-       }
-
-       geninst->data.generic_class = gclass;
-
        mono_loader_unlock ();
 
-       return geninst;
+       geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
+
+       return &geninst->byval_arg;
 }
 
-MonoType*
-mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
+MonoClass*
+mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
 {
-       MonoClass *klass;
-       MonoGenericClass *gclass, *cached;
-       MonoInflatedGenericClass *igclass;
-       MonoType *geninst;
-       int i;
-
-       klass = mono_class_from_mono_type (type);
-       if (!klass->generic_container && !klass->generic_class &&
-           !(klass->nested_in && klass->nested_in->generic_container))
-               return NULL;
-
-       mono_loader_lock ();
-
-       igclass = g_new0 (MonoInflatedGenericClass, 1);
-       gclass = &igclass->generic_class;
-       gclass->is_inflated = TRUE;
-
-       gclass->inst = g_new0 (MonoGenericInst, 1);
-       gclass->inst->type_argc = type_argc;
-       gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
-       gclass->inst->is_reference = 1;
-
-       for (i = 0; i < gclass->inst->type_argc; ++i) {
-               MonoType *t = dup_type (types [i]);
-
-               if (!gclass->inst->is_open)
-                       gclass->inst->is_open = mono_class_is_open_constructed_type (t);
-               if (gclass->inst->is_reference)
-                       gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
-
-               gclass->inst->type_argv [i] = t;
-       }
-
-       gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
-
-       gclass->container_class = klass;
-
-       if (klass->generic_class) {
-               MonoGenericClass *kgclass = klass->generic_class;
-               MonoGenericClass *ogclass = gclass;
-
-               igclass = g_new0 (MonoInflatedGenericClass, 1);
-               gclass = &igclass->generic_class;
-               gclass->is_inflated = TRUE;
-
-               gclass->inst = g_new0 (MonoGenericInst, 1);
-               gclass->inst->type_argc = kgclass->inst->type_argc;
-               gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
-               gclass->inst->is_reference = 1;
-
-               for (i = 0; i < gclass->inst->type_argc; i++) {
-                       MonoType *t = kgclass->inst->type_argv [i];
-
-                       t = mono_class_inflate_generic_type (t, mono_generic_class_get_context (ogclass));
-
-                       if (!gclass->inst->is_open)
-                               gclass->inst->is_open = mono_class_is_open_constructed_type (t);
-                       if (gclass->inst->is_reference)
-                               gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
-
-                       gclass->inst->type_argv [i] = t;
-               }
-
-               gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
-
-               gclass->container_class = kgclass->container_class;
-       }
-
-       geninst = g_new0 (MonoType, 1);
-       geninst->type = MONO_TYPE_GENERICINST;
-
-       cached = mono_metadata_lookup_generic_class (gclass);
-       if (cached) {
-               g_free (gclass);
-               mono_loader_unlock ();
-               geninst->data.generic_class = cached;
-               return geninst;
-       }
-
-       geninst->data.generic_class = gclass;
+       MonoGenericClass *gclass;
+       MonoGenericInst *inst;
 
-       mono_loader_unlock ();
+       g_assert (klass->generic_container);
 
-       return geninst;
-}
+       inst = mono_metadata_get_generic_inst (type_argc, types);
+       gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
 
-static inline MonoType*
-dup_type (const MonoType *original)
-{
-       MonoType *r = g_new0 (MonoType, 1);
-       *r = *original;
-       r->attrs = original->attrs;
-       r->byref = original->byref;
-       if (original->type == MONO_TYPE_PTR)
-               r->data.type = dup_type (original->data.type);
-       else if (original->type == MONO_TYPE_ARRAY)
-               r->data.array = mono_dup_array_type (original->data.array);
-       else if (original->type == MONO_TYPE_FNPTR)
-               r->data.method = mono_metadata_signature_deep_dup (original->data.method);
-       mono_stats.generics_metadata_size += sizeof (MonoType);
-       return r;
+       return mono_generic_class_get_class (gclass);
 }
 
 MonoReflectionMethod*
 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
 {
+       MonoClass *klass;
        MonoMethod *method, *inflated;
+       MonoMethodInflated *imethod;
        MonoReflectionMethodBuilder *mb = NULL;
-       MonoGenericContainer *container;
-       MonoGenericMethod *gmethod;
-       MonoGenericContext *context;
+       MonoGenericContext tmp_context;
        MonoGenericInst *ginst;
+       MonoType **type_argv;
        int count, i;
 
        MONO_ARCH_SAVE_REGS;
@@ -8905,60 +8992,31 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
                method = rmethod->method;
        }
 
-       method = mono_get_inflated_method (method);
+       klass = method->klass;
+
+       if (method->is_inflated)
+               method = ((MonoMethodInflated *) method)->declaring;
 
        count = mono_method_signature (method)->generic_param_count;
        if (count != mono_array_length (types))
                return NULL;
 
-       container = 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);
-       ginst->is_reference = 1;
+       type_argv = g_new0 (MonoType *, count);
        for (i = 0; i < count; i++) {
                MonoReflectionType *garg = mono_array_get (types, gpointer, i);
-               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]);
-               if (ginst->is_reference)
-                       ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
+               type_argv [i] = garg->type;
        }
-       ginst = mono_metadata_lookup_generic_inst (ginst);
+       ginst = mono_metadata_get_generic_inst (count, type_argv);
+       g_free (type_argv);
 
-       gmethod = g_new0 (MonoGenericMethod, 1);
-       if (method->klass->generic_class)
-               gmethod->class_inst = method->klass->generic_class->inst;
-       gmethod->container = container;
-       gmethod->inst = ginst;
+       tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
+       tmp_context.method_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);
-       }
-
-       MOVING_GC_REGISTER (&gmethod->reflection_info);
-       gmethod->reflection_info = rmethod;
-
-       context = g_new0 (MonoGenericContext, 1);
-       context->class_inst = gmethod->class_inst;
-       context->gmethod = gmethod;
-
-       if (method->is_inflated)
-               method = ((MonoMethodInflated *) method)->declaring;
+       inflated = mono_class_inflate_generic_method (method, &tmp_context);
+       imethod = (MonoMethodInflated *) inflated;
 
-       inflated = mono_class_inflate_generic_method (method, context);
-       g_hash_table_insert (container->method_hash, gmethod, inflated);
+       MOVING_GC_REGISTER (&imethod->reflection_info);
+       imethod->reflection_info = rmethod;
 
        return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
 }
@@ -8966,41 +9024,20 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
 static MonoMethod *
 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
 {
-       MonoGenericMethod *gmethod = NULL;
+       MonoMethodInflated *imethod;
        MonoGenericContext *context;
        MonoClass *klass;
-       int i, n;
 
        klass = mono_class_from_mono_type (type->type.type);
        g_assert (klass->generic_class);
        context = mono_class_get_context (klass);
 
-       n = mono_method_signature (method)->generic_param_count;
-       if (n) {
-               gmethod = g_new0 (MonoGenericMethod, 1);
-               gmethod->class_inst = klass->generic_class->inst;
-               gmethod->container = method->generic_container;
-               MOVING_GC_REGISTER (&gmethod->reflection_info);
-               gmethod->reflection_info = obj;
-
-               gmethod->inst = g_new0 (MonoGenericInst, 1);
-               gmethod->inst->type_argc = n;
-               gmethod->inst->type_argv = g_new0 (MonoType *, n);
-
-               for (i = 0; i < n; i++) {
-                       MonoGenericParam *gparam = &method->generic_container->type_params [i];
-                       g_assert (gparam->pklass);
-                       gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
-               }
-
-               g_assert (gmethod->container->parent == klass->generic_class->container_class->generic_container);
-
-               context = g_new0 (MonoGenericContext, 1);
-               context->class_inst = klass->generic_class->inst;
-               context->gmethod = gmethod;
+       imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
+       if (method->generic_container) {
+               MOVING_GC_REGISTER (&imethod->reflection_info);
+               imethod->reflection_info = obj;
        }
-
-       return mono_class_inflate_generic_method (method, context);
+       return (MonoMethod *) imethod;
 }
 
 static MonoMethod *
@@ -9009,7 +9046,7 @@ inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
        MonoMethod *method;
        MonoClass *gklass;
 
-       gklass = mono_class_from_mono_type (type->generic_type->type);
+       gklass = mono_class_from_mono_type (type->generic_type->type.type);
 
        if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
                method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
@@ -9038,6 +9075,7 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
        MONO_ARCH_SAVE_REGS;
 
        klass = mono_class_from_mono_type (type->type.type);
+       g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
        gclass = type->type.type->data.generic_class;
 
        g_assert (gclass->is_dynamic);
@@ -9400,6 +9438,20 @@ typebuilder_setup_events (MonoClass *klass)
        }
 }
 
+static gboolean
+remove_instantiations_of (gpointer key,
+                                                 gpointer value,
+                                                 gpointer user_data)
+{
+       MonoType *type = (MonoType*)key;
+       MonoClass *klass = (MonoClass*)user_data;
+
+       if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
+               return TRUE;
+       else
+               return FALSE;
+}
+
 MonoReflectionType*
 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
 {
@@ -9479,11 +9531,25 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        typebuilder_setup_properties (klass);
 
        typebuilder_setup_events (klass);
-
+       
        klass->wastypebuilder = TRUE;
+
+       /* 
+        * If we are a generic TypeBuilder, there might be instantiations in the type cache
+        * which have type System.Reflection.MonoGenericClass, but after the type is created, 
+        * we want to return normal System.MonoType objects, so clear these out from the cache.
+        */
+       if (domain->type_hash && klass->generic_container)
+               mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
+
        mono_loader_unlock ();
        mono_domain_unlock (domain);
 
+       if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
+               mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+               mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
+       }
+
        res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
        g_assert (res != (MonoReflectionType*)tb);
 
@@ -9501,15 +9567,16 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam
        param = g_new0 (MonoGenericParam, 1);
 
        if (gparam->mbuilder) {
-               if (!gparam->mbuilder->generic_container)
+               if (!gparam->mbuilder->generic_container) {
                        gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
+                       gparam->mbuilder->generic_container->is_method = TRUE;
+               }
                param->owner = gparam->mbuilder->generic_container;
        } else if (gparam->tbuilder) {
                g_assert (gparam->tbuilder->generic_container);
                param->owner = gparam->tbuilder->generic_container;
        }
 
-       param->method = NULL;
        param->name = mono_string_to_utf8 (gparam->name);
        param->num = gparam->index;
 
@@ -9530,27 +9597,23 @@ mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
 {
        MonoDynamicImage *assembly = sig->module->dynamic_image;
        guint32 na = mono_array_length (sig->arguments);
-       guint32 buflen, i, size;
+       guint32 buflen, i;
        MonoArray *result;
-       char *buf, *p;
-
-       MONO_ARCH_SAVE_REGS;
+       SigBuffer buf;
 
-       p = buf = g_malloc (size = 50 + na * 50);
+       sigbuffer_init (&buf, 32);
 
-       mono_metadata_encode_value (0x07, p, &p);
-       mono_metadata_encode_value (na, p, &p);
+       sigbuffer_add_value (&buf, 0x07);
+       sigbuffer_add_value (&buf, na);
        for (i = 0; i < na; ++i) {
                MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
-               encode_reflection_type (assembly, type, p, &p);
+               encode_reflection_type (assembly, type, &buf);
        }
 
-       buflen = p - buf;
-       g_assert (buflen < size);
+       buflen = buf.p - buf.buf;
        result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
-       p = mono_array_addr (result, char, 0);
-       memcpy (p, buf, buflen);
-       g_free (buf);
+       memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
+       sigbuffer_free (&buf);
 
        return result;
 }
@@ -9560,26 +9623,22 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
 {
        MonoDynamicImage *assembly = sig->module->dynamic_image;
        guint32 na = mono_array_length (sig->arguments);
-       guint32 buflen, i, size;
+       guint32 buflen, i;
        MonoArray *result;
-       char *buf, *p;
-
-       MONO_ARCH_SAVE_REGS;
+       SigBuffer buf;
 
-       p = buf = g_malloc (size = 10 + na * 10);
+       sigbuffer_init (&buf, 32);
 
-       mono_metadata_encode_value (0x06, p, &p);
+       sigbuffer_add_value (&buf, 0x06);
        for (i = 0; i < na; ++i) {
                MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
-               encode_reflection_type (assembly, type, p, &p);
+               encode_reflection_type (assembly, type, &buf);
        }
 
-       buflen = p - buf;
-       g_assert (buflen < size);
+       buflen = buf.p - buf.buf;
        result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
-       p = mono_array_addr (result, char, 0);
-       memcpy (p, buf, buflen);
-       g_free (buf);
+       memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
+       sigbuffer_free (&buf);
 
        return result;
 }
@@ -9589,6 +9648,8 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
 {
        ReflectionMethodBuilder rmb;
        MonoMethodSignature *sig;
+       MonoClass *klass;
+       GSList *l;
        int i;
 
        sig = dynamic_method_to_signature (mb);
@@ -9606,19 +9667,59 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
        rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
        for (i = 0; i < mb->nrefs; i += 2) {
                MonoClass *handle_class;
-               gpointer ref = resolve_object (mb->module->image, 
-                                              mono_array_get (mb->refs, MonoObject*, i), &handle_class);
-               if (!ref) {
-                       g_free (rmb.refs);
-                       mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
-                       return;
+               gpointer ref;
+               MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
+
+               if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
+                       MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
+                       /*
+                        * The referenced DynamicMethod should already be created by the managed
+                        * code, except in the case of circular references. In that case, we store
+                        * method in the refs array, and fix it up later when the referenced 
+                        * DynamicMethod is created.
+                        */
+                       if (method->mhandle) {
+                               ref = method->mhandle;
+                       } else {
+                               /* FIXME: GC object stored in unmanaged memory */
+                               ref = method;
+
+                               /* FIXME: GC object stored in unmanaged memory */
+                               method->referenced_by = g_slist_append (method->referenced_by, mb);
+                       }
+                       handle_class = mono_defaults.methodhandle_class;
+               } else {
+                       ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
+                       if (!ref) {
+                               g_free (rmb.refs);
+                               mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
+                               return;
+                       }
                }
+
                rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
                rmb.refs [i + 1] = handle_class;
        }               
 
-       /* FIXME: class */
-       mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
+       klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
+
+       mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+
+       /* Fix up refs entries pointing at us */
+       for (l = mb->referenced_by; l; l = l->next) {
+               MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
+               MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
+               gpointer *data;
+               
+               g_assert (method->mhandle);
+
+               data = (gpointer*)wrapper->method_data;
+               for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
+                       if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
+                               data [i + 1] = mb->mhandle;
+               }
+       }
+       g_slist_free (mb->referenced_by);
 
        g_free (rmb.refs);
 
@@ -9626,27 +9727,46 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
        mb->ilgen = NULL;
 }
 
+void
+mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
+{
+       g_assert (mb);
+
+       if (mb->mhandle)
+               mono_runtime_free_method (
+                       mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
+}
+
 /**
  * mono_reflection_lookup_dynamic_token:
  *
  * Finish the Builder object pointed to by TOKEN and return the corresponding
- * runtime structure. HANDLE_CLASS is set to the class required by 
- * mono_ldtoken.
+ * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
+ * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
+ * mapping table.
  */
 gpointer
-mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
 {
        MonoDynamicImage *assembly = (MonoDynamicImage*)image;
        MonoObject *obj;
+       MonoClass *klass;
 
        obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
-       g_assert (obj);
+       if (!obj) {
+               if (valid_token)
+                       g_assert_not_reached ();
+               else
+                       return NULL;
+       }
 
-       return resolve_object (image, obj, handle_class);
+       if (!handle_class)
+               handle_class = &klass;
+       return resolve_object (image, obj, handle_class, context);
 }
 
 static gpointer
-resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
+resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
 {
        gpointer result = NULL;
 
@@ -9656,7 +9776,13 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
                g_assert (result);
        } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
                MonoReflectionType *tb = (MonoReflectionType*)obj;
-               result = mono_class_from_mono_type (tb->type);
+               if (context) {
+                       MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
+                       result = mono_class_from_mono_type (inflated);
+                       mono_metadata_free_type (inflated);
+               } else {
+                       result = mono_class_from_mono_type (tb->type);
+               }
                *handle_class = mono_defaults.typehandle_class;
                g_assert (result);
        } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
@@ -9664,6 +9790,7 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
                   strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
                   strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
                result = ((MonoReflectionMethod*)obj)->method;
+               result = mono_class_inflate_generic_method (result, context);
                *handle_class = mono_defaults.methodhandle_class;
                g_assert (result);
        } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
@@ -9685,6 +9812,7 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
                         */
                        result = mb->mhandle;
                }
+               result = mono_class_inflate_generic_method (result, context);
                *handle_class = mono_defaults.methodhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
                MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
@@ -9696,6 +9824,7 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
                        mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
                        result = cb->mhandle;
                }
+               result = mono_class_inflate_generic_method (result, context);
                *handle_class = mono_defaults.methodhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
                result = ((MonoReflectionField*)obj)->field;
@@ -9711,6 +9840,14 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
                        mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
                        result = fb->handle;
                }
+
+               if (fb->handle && fb->handle->parent->generic_container) {
+                       MonoClass *klass = fb->handle->parent;
+                       MonoClass *inflated = mono_class_from_mono_type (mono_class_inflate_generic_type (&klass->byval_arg, context));
+
+                       result = mono_class_get_field_from_name (inflated, fb->handle->name);
+                       g_assert (result);
+               }
                *handle_class = mono_defaults.fieldhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
@@ -9765,6 +9902,16 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
                g_assert (method->mhandle);
                result = method->mhandle;
                *handle_class = mono_defaults.methodhandle_class;
+       } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
+               MonoReflectionType *tb = (MonoReflectionType*)obj;
+               result = mono_class_from_mono_type (mono_class_inflate_generic_type (tb->type, context));
+               *handle_class = mono_defaults.typehandle_class;
+               g_assert (result);
+       } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
+               MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
+               result = mono_class_from_mono_type (mono_class_inflate_generic_type (ref->type.type, context));
+               *handle_class = mono_defaults.typehandle_class;
+               g_assert (result);
        } else {
                g_print (obj->vtable->klass->name);
                g_assert_not_reached ();
@@ -9804,12 +9951,17 @@ const static guint32 declsec_flags_map[] = {
 static guint32
 mono_declsec_get_flags (MonoImage *image, guint32 token)
 {
-       guint32 index = mono_metadata_declsec_from_index (image, token);
+       int index = mono_metadata_declsec_from_index (image, token);
        MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
        guint32 result = 0;
        guint32 action;
        int i;
 
+       /* HasSecurity can be present for other, not specially encoded, attributes,
+          e.g. SuppressUnmanagedCodeSecurityAttribute */
+       if (index < 0)
+               return 0;
+
        for (i = index; i < t->rows; i++) {
                guint32 cols [MONO_DECL_SECURITY_SIZE];