Mark tests as not working under TARGET_JVM
[mono.git] / mono / metadata / reflection.c
index 59deed92ac2ba8d597cbcfa088fc82924a46e5d4..8e71602f69bacb451674123050c11363967a3760 100644 (file)
 #include "mono-endian.h"
 #include <mono/os/gc_wrapper.h>
 
+typedef struct {
+       char *p;
+       char *buf;
+       char *end;
+} SigBuffer;
+
 #define TEXT_OFFSET 512
 #define CLI_H_SIZE 136
 #define FILE_ALIGN 512
@@ -138,11 +144,71 @@ static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, gui
 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 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);
+
+#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:
@@ -239,6 +305,16 @@ string_heap_insert (MonoDynamicStream *sh, const char *str)
        return idx;
 }
 
+static guint32
+string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
+{
+       char *name = mono_string_to_utf8 (str);
+       guint32 idx;
+       idx = string_heap_insert (sh, name);
+       g_free (name);
+       return idx;
+}
+
 static void
 string_heap_init (MonoDynamicStream *sh)
 {
@@ -338,6 +414,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.
@@ -473,7 +561,7 @@ 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;
 
@@ -482,17 +570,16 @@ encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char
                return;
        }
 
-       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);
+       sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
+       encode_type (assembly, &gclass->container_class->byval_arg, buf);
+       sigbuffer_add_value (buf, gclass->inst->type_argc);
        for (i = 0; i < gclass->inst->type_argc; ++i)
-               encode_type (assembly, gclass->inst->type_argv [i], p, &p);
+               encode_type (assembly, gclass->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 ();
@@ -500,7 +587,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:
@@ -521,15 +608,15 @@ 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: {
@@ -537,45 +624,46 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
                /*
                 * Make sure we use the correct type.
                 */
-               mono_metadata_encode_value (k->byval_arg.type, p, &p);
+               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.
                 */
-               mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
+               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;
        }
 
@@ -584,156 +672,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;
 }
 
@@ -743,32 +733,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;
@@ -778,24 +764,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;
 }
 
@@ -804,36 +787,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;
 
@@ -1011,7 +988,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) {
@@ -1081,8 +1058,21 @@ 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;
+       mono_reflection_lock ();
+       ainfo = g_hash_table_lookup (dynamic_custom_attrs, member);
+       mono_reflection_unlock ();
+       return ainfo;
+}
+
 static gboolean
 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
 {
@@ -1125,16 +1115,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;
 }
@@ -1147,11 +1140,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
@@ -1266,7 +1261,6 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly
 {
        MonoDynamicTable *table;
        guint32 *values;
-       char *name;
        guint i, count;
 
        /* room in this table is already allocated */
@@ -1274,9 +1268,7 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly
        *mb->table_idx = table->next_idx ++;
        g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
        values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
-       name = mono_string_to_utf8 (mb->name);
-       values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
-       g_free (name);
+       values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
        values [MONO_METHOD_FLAGS] = mb->attrs;
        values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
        values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
@@ -1309,9 +1301,7 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly
                                values [MONO_PARAM_FLAGS] = pb->attrs;
                                values [MONO_PARAM_SEQUENCE] = i;
                                if (pb->name != NULL) {
-                                       name = mono_string_to_utf8 (pb->name);
-                                       values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
-                                       g_free (name);
+                                       values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
                                } else {
                                        values [MONO_PARAM_NAME] = 0;
                                }
@@ -1472,7 +1462,6 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *a
 {
        MonoDynamicTable *table;
        guint32 *values;
-       char *name;
        ReflectionMethodBuilder rmb;
        int i;
 
@@ -1494,14 +1483,10 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *a
                values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
                values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
                if (mb->dllentry)
-                       name = mono_string_to_utf8 (mb->dllentry);
+                       values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
                else
-                       name = mono_string_to_utf8 (mb->name);
-               values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
-               g_free (name);
-               name = mono_string_to_utf8 (mb->dll);
-               moduleref = string_heap_insert (&assembly->sheap, name);
-               g_free (name);
+                       values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
+               moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
                if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
                        table = &assembly->tables [MONO_TABLE_MODULEREF];
                        table->rows ++;
@@ -1560,46 +1545,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 +1662,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 +1685,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;
+
+       sigbuffer_init (&buf, 32);
 
-       mono_metadata_encode_value (minfo->type, p, &p);
+       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 +1714,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 +1729,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;
 }
 
@@ -1808,7 +1759,6 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *ass
 {
        MonoDynamicTable *table;
        guint32 *values;
-       char *name;
 
        /* maybe this fixup should be done in the C# code */
        if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
@@ -1817,9 +1767,7 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *ass
        fb->table_idx = table->next_idx ++;
        g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
        values = table->values + fb->table_idx * MONO_FIELD_SIZE;
-       name = mono_string_to_utf8 (fb->name);
-       values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
-       g_free (name);
+       values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
        values [MONO_FIELD_FLAGS] = fb->attrs;
        values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
 
@@ -1852,9 +1800,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;
        }
@@ -1871,46 +1821,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) {
+       } 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;
 }
 
@@ -1919,7 +1861,6 @@ mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImag
 {
        MonoDynamicTable *table;
        guint32 *values;
-       char *name;
        guint num_methods = 0;
        guint32 semaidx;
 
@@ -1933,9 +1874,7 @@ mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImag
        table = &assembly->tables [MONO_TABLE_PROPERTY];
        pb->table_idx = table->next_idx ++;
        values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
-       name = mono_string_to_utf8 (pb->name);
-       values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
-       g_free (name);
+       values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
        values [MONO_PROPERTY_FLAGS] = pb->attrs;
        values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
 
@@ -1968,7 +1907,6 @@ mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *ass
 {
        MonoDynamicTable *table;
        guint32 *values;
-       char *name;
        guint num_methods = 0;
        guint32 semaidx;
 
@@ -1982,9 +1920,7 @@ mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *ass
        table = &assembly->tables [MONO_TABLE_EVENT];
        eb->table_idx = table->next_idx ++;
        values = table->values + eb->table_idx * MONO_EVENT_SIZE;
-       name = mono_string_to_utf8 (eb->name);
-       values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
-       g_free (name);
+       values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
        values [MONO_EVENT_FLAGS] = eb->attrs;
        values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
 
@@ -2074,6 +2010,10 @@ mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 o
 
        entry = g_new0 (GenericParamTableEntry, 1);
        entry->owner = owner;
+#ifdef HAVE_SGEN_GC
+       /* FIXME: track where gen_params should be freed and remove the GC root as well */
+       MONO_GC_REGISTER_ROOT (entry->gparam);
+#endif
        entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
 
        g_ptr_array_add (assembly->gen_params, entry);
@@ -2162,8 +2102,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;
        }
@@ -2179,11 +2119,9 @@ 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;
 
+       sigbuffer_init (&buf, 32);
        switch (type->type) {
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_PTR:
@@ -2192,29 +2130,31 @@ 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_class) {
+                       sigbuffer_free (&buf);
                        return 0;
-               encode_generic_class (assembly, k->generic_class, p, &p);
+               }
+               encode_generic_class (assembly, k->generic_class, &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));
@@ -2428,33 +2368,26 @@ mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *
 static guint32
 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
 {
-       char *buf;
-       char *p;
+       SigBuffer buf;
        int i;
        guint32 nparams =  gmethod->inst->type_argc;
-       guint32 size = 10 + nparams * 30;
        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, gmethod->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;
 }
 
@@ -2470,7 +2403,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;
 
@@ -2491,7 +2423,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)->gmethod);
 
        if (assembly->save) {
                alloc_table (table, table->rows + 1);
@@ -2556,10 +2488,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;
 
        /*
@@ -2572,32 +2501,33 @@ 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);
+       sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
+       encode_type (assembly, &klass->byval_arg, &buf);
 
        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));
@@ -2648,13 +2578,10 @@ 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;
@@ -2669,7 +2596,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 */
@@ -2680,26 +2607,23 @@ 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);
+               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;
 }
@@ -3099,7 +3023,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 ++;
 }
 
@@ -3108,13 +3032,10 @@ mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *m
 {
        MonoDynamicTable *table;
        int i;
-       char *name;
 
        table = &assembly->tables [MONO_TABLE_MODULE];
        mb->table_idx = table->next_idx ++;
-       name = mono_string_to_utf8 (mb->module.name);
-       table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
-       g_free (name);
+       table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
        i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
        i /= 16;
        ++i;
@@ -3424,7 +3345,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 */
@@ -3459,7 +3380,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);
        }
@@ -3467,7 +3388,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;
@@ -3532,7 +3453,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) {
@@ -3590,7 +3511,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")) {
@@ -3705,7 +3626,6 @@ assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImag
 {
        MonoDynamicTable *table;
        guint32 *values;
-       char *name;
 
        table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
        table->rows++;
@@ -3713,9 +3633,7 @@ assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImag
        values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
        values [MONO_MANIFEST_OFFSET] = rsrc->offset;
        values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
-       name = mono_string_to_utf8 (rsrc->name);
-       values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
-       g_free (name);
+       values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
        values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
        table->next_idx++;
 }
@@ -3746,18 +3664,27 @@ 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;
                idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
        } else {
                char sizebuf [4];
-               offset = mono_array_length (rsrc->data);
+               char *data;
+               guint len;
+               if (rsrc->data) {
+                       data = mono_array_addr (rsrc->data, char, 0);
+                       len = mono_array_length (rsrc->data);
+               } else {
+                       data = NULL;
+                       len = 0;
+               }
+               offset = len;
                sizebuf [0] = offset; sizebuf [1] = offset >> 8;
                sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
                rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
-               mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
+               mono_image_add_stream_data (&assembly->resources, data, len);
 
                if (!mb->is_main)
                        /* 
@@ -3815,10 +3742,10 @@ 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);
 
        /* 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) {
@@ -3842,7 +3769,6 @@ mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
        MonoReflectionAssemblyBuilder *assemblyb;
        MonoDomain *domain;
        guint32 *values;
-       char *name;
        int i;
        guint32 module_index;
 
@@ -3855,13 +3781,9 @@ mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
        alloc_table (table, 1);
        values = table->values + MONO_ASSEMBLY_SIZE;
        values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
-       name = mono_string_to_utf8 (assemblyb->name);
-       values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
-       g_free (name);
+       values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
        if (assemblyb->culture) {
-               name = mono_string_to_utf8 (assemblyb->culture);
-               values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
-               g_free (name);
+               values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
        } else {
                values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
        }
@@ -4008,19 +3930,11 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
         */
        for (i = 0; i < types->len; ++i) {
                MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
-               char *n;
-
-               n = mono_string_to_utf8 (tb->nspace);
-               string_heap_insert (&assembly->sheap, n);
-               g_free (n);
+               string_heap_insert_mstring (&assembly->sheap, tb->nspace);
        }
        for (i = 0; i < types->len; ++i) {
                MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
-               char *n;
-
-               n = mono_string_to_utf8 (tb->name);
-               string_heap_insert (&assembly->sheap, n);
-               g_free (n);
+               string_heap_insert_mstring (&assembly->sheap, tb->name);
        }
 
        for (i = 0; i < types->len; ++i) {
@@ -4298,6 +4212,10 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean c
        } else if (strcmp (klass->name, "SignatureHelper") == 0) {
                MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
                token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
+       } else if (strcmp (klass->name, "EnumBuilder") == 0) {
+               MonoReflectionType *tb = (MonoReflectionType *)obj;
+               token = mono_metadata_token_from_dor (
+                       mono_image_typedef_or_ref (assembly, tb->type));
        } else {
                g_error ("requested token for %s\n", klass->name);
        }
@@ -4368,7 +4286,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 */
@@ -4790,7 +4708,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));
@@ -4939,7 +4857,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);
@@ -4980,7 +4898,7 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
        /* write the section tables and section content */
        section = (MonoSectionTable*)(pefile->data + section_start);
        for (i = 0; i < MONO_SECTION_MAX; ++i) {
-               static const char *section_names [] = {
+               static const char section_names [][7] = {
                        ".text", ".rsrc", ".reloc"
                };
                if (!assembly->sections [i].size)
@@ -5010,7 +4928,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;
@@ -5300,13 +5218,14 @@ mono_module_get_object   (MonoDomain *domain, MonoImage *image)
                res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
        } else {
                int i;
-               g_assert (image->assembly->image->modules);
                res->token = 0;
-               for (i = 0; i < image->assembly->image->module_count; i++) {
-                       if (image->assembly->image->modules [i] == image)
-                               res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
+               if (image->assembly->image->modules) {
+                       for (i = 0; i < image->assembly->image->module_count; i++) {
+                               if (image->assembly->image->modules [i] == image)
+                                       res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
+                       }
+                       g_assert (res->token);
                }
-               g_assert (res->token);
        }
 
        CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
@@ -5451,8 +5370,7 @@ mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
 {
        static MonoClass *System_Reflection_MonoGenericClass;
        MonoReflectionGenericClass *res;
-       MonoInflatedGenericClass *gclass;
-       MonoClass *gklass;
+       MonoClass *klass, *gklass;
 
        if (!System_Reflection_MonoGenericClass) {
                System_Reflection_MonoGenericClass = mono_class_from_name (
@@ -5460,13 +5378,17 @@ mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
                g_assert (System_Reflection_MonoGenericClass);
        }
 
-       gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
-       gklass = gclass->generic_class.container_class;
-       g_assert (gklass->generic_container);
+       klass = mono_class_from_mono_type (geninst);
+       gklass = klass->generic_class->container_class;
 
-       mono_class_init (gclass->klass);
+       mono_class_init (klass);
 
+#ifdef HAVE_SGEN_GC
+       /* FIXME: allow unpinned later */
+       res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
+#else
        res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
+#endif
 
        res->type.type = geninst;
        if (gklass->wastypebuilder && gklass->reflection_info)
@@ -5574,7 +5496,10 @@ mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refcl
         * We use the same C representation for methods and constructors, but the type 
         * name in C# is different.
         */
-       const char *cname;
+       static MonoClass *System_Reflection_MonoMethod = NULL;
+       static MonoClass *System_Reflection_MonoCMethod = NULL;
+       static MonoClass *System_Reflection_MonoGenericMethod = NULL;
+       static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
        MonoClass *klass;
        MonoReflectionMethod *ret;
 
@@ -5584,12 +5509,15 @@ mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refcl
                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")))
-                       cname = "MonoGenericCMethod";
-               else
-                       cname = "MonoGenericMethod";
-               klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
-
+               if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
+                       if (!System_Reflection_MonoGenericCMethod)
+                               System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
+                       klass = System_Reflection_MonoGenericCMethod;
+               } else {
+                       if (!System_Reflection_MonoGenericMethod)
+                               System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
+                       klass = System_Reflection_MonoGenericMethod;
+               }
                gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
                gret->method.method = method;
                MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
@@ -5601,12 +5529,16 @@ mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refcl
                refclass = method->klass;
 
        CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
-       if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
-               cname = "MonoCMethod";
-       else
-               cname = "MonoMethod";
-       klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
-
+       if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
+               if (!System_Reflection_MonoCMethod)
+                       System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
+               klass = System_Reflection_MonoCMethod;
+       }
+       else {
+               if (!System_Reflection_MonoMethod)
+                       System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
+               klass = System_Reflection_MonoMethod;
+       }
        ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
        ret->method = method;
        MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
@@ -6068,7 +6000,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 != ',')
@@ -6733,7 +6665,7 @@ handle_type:
                        n [slen] = 0;
                        t = mono_reflection_type_from_name (n, image);
                        if (!t)
-                               g_warning ("Cannot load type '%s'", n);
+                               g_error ("Cannot load type '%s'", n);
                        g_free (n);
                        p += slen;
                        subc = mono_class_from_mono_type (t);
@@ -6761,6 +6693,8 @@ handle_type:
                }
                arr = mono_array_new (mono_domain_get(), tklass, alen);
                basetype = tklass->byval_arg.type;
+               if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
+                       basetype = tklass->enum_basetype->type;
                switch (basetype)
                {
                        case MONO_TYPE_U1:
@@ -6807,7 +6741,7 @@ handle_type:
                                }
                                break;
                        default:
-                               g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
+                               g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
                }
                *end=p;
                return arr;
@@ -6977,14 +6911,12 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
        named += 2;
        for (j = 0; j < num_named; j++) {
                gint name_len;
-               gboolean is_boxed = FALSE;
                char *name, named_type, data_type;
                named_type = *named++;
                data_type = *named++; /* type of data */
-               if (data_type == 0x51)
-                       is_boxed = TRUE;
-
-               if (data_type == 0x55) {
+               if (data_type == MONO_TYPE_SZARRAY)
+                       data_type = *named++;
+               if (data_type == MONO_TYPE_ENUM) {
                        gint type_len;
                        char *type_name;
                        type_len = mono_metadata_decode_blob_size (named, &named);
@@ -6994,10 +6926,6 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
                        named += type_len;
                        /* FIXME: lookup the type and check type consistency */
                        g_free (type_name);
-               } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
-                       /* this seems to be the type of the element of the array */
-                       /* g_print ("skipping 0x%02x after prop\n", *named); */
-                       named++;
                }
                name_len = mono_metadata_decode_blob_size (named, &named);
                name = g_malloc (name_len + 1);
@@ -7092,7 +7020,9 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat
                char *name, named_type, data_type;
                named_type = *named++;
                data_type = *named++; /* type of data */
-               if (data_type == 0x55) {
+               if (data_type == MONO_TYPE_SZARRAY)
+                       data_type = *named++;
+               if (data_type == MONO_TYPE_ENUM) {
                        gint type_len;
                        char *type_name;
                        type_len = mono_metadata_decode_blob_size (named, &named);
@@ -7102,10 +7032,6 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat
                        named += type_len;
                        /* FIXME: lookup the type and check type consistency */
                        g_free (type_name);
-               } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
-                       /* this seems to be the type of the element of the array */
-                       /* g_print ("skipping 0x%02x after prop\n", *named); */
-                       named++;
                }
                name_len = mono_metadata_decode_blob_size (named, &named);
                name = g_malloc (name_len + 1);
@@ -7274,7 +7200,7 @@ mono_custom_attrs_from_method (MonoMethod *method)
        MonoCustomAttrInfo *cinfo;
        guint32 idx;
        
-       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;
@@ -7288,7 +7214,7 @@ mono_custom_attrs_from_class (MonoClass *klass)
        MonoCustomAttrInfo *cinfo;
        guint32 idx;
        
-       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;
@@ -7302,7 +7228,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;
@@ -7316,7 +7242,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;
@@ -7330,7 +7256,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;
@@ -7344,7 +7270,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;
@@ -7358,7 +7284,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;
@@ -7386,11 +7312,6 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
        method_index = mono_method_get_index (method);
        ca = &image->tables [MONO_TABLE_METHOD];
 
-       if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
-               /* FIXME FIXME FIXME */
-               return NULL;
-       }
-
        param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
        if (method_index == ca->rows) {
                ca = &image->tables [MONO_TABLE_PARAM];
@@ -7593,6 +7514,31 @@ mono_reflection_get_custom_attrs_data (MonoObject *obj)
        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.
  */
@@ -7608,7 +7554,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;
 }
@@ -7777,8 +7723,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 types 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);
@@ -7868,10 +7824,10 @@ 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;
+                       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;
@@ -7903,28 +7859,8 @@ handle_type:
 }
 
 static void
-encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
+encode_field_or_prop_type (MonoType *type, char *p, char **retp)
 {
-       int len;
-       /* Preallocate a large enough buffer */
-       if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
-               char *str = type_get_qualified_name (type, NULL);
-               len = strlen (str);
-               g_free (str);
-       } else {
-               len = 0;
-       }
-       len += strlen (name);
-
-       if ((p-buffer) + 20 + len >= *buflen) {
-               char *newbuf;
-               *buflen *= 2;
-               *buflen += len;
-               newbuf = g_realloc (buffer, *buflen);
-               p = newbuf + (p-buffer);
-               buffer = newbuf;
-       }
-
        if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
                char *str = type_get_qualified_name (type, NULL);
                int slen = strlen (str);
@@ -7946,8 +7882,42 @@ encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char
        } else {
                mono_metadata_encode_value (type->type, p, &p);
                if (type->type == MONO_TYPE_SZARRAY)
-                       mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
+                       /* See the examples in Partition VI, Annex B */
+                       encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
        }
+
+       *retp = p;
+}
+
+static void
+encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
+{
+       int len;
+       /* Preallocate a large enough buffer */
+       if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
+               char *str = type_get_qualified_name (type, NULL);
+               len = strlen (str);
+               g_free (str);
+       } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
+               char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
+               len = strlen (str);
+               g_free (str);
+       } else {
+               len = 0;
+       }
+       len += strlen (name);
+
+       if ((p-buffer) + 20 + len >= *buflen) {
+               char *newbuf;
+               *buflen *= 2;
+               *buflen += len;
+               newbuf = g_realloc (buffer, *buflen);
+               p = newbuf + (p-buffer);
+               buffer = newbuf;
+       }
+
+       encode_field_or_prop_type (type, p, &p);
+
        len = strlen (name);
        mono_metadata_encode_value (len, p, &p);
        memcpy (p, name, len);
@@ -8046,6 +8016,15 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
 
 #if HAVE_SGEN_GC
 static void* reflection_info_desc = NULL;
+#define MOVING_GC_REGISTER(addr) do {  \
+               if (!reflection_info_desc) {    \
+                       gsize bmap = 1;         \
+                       reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);       \
+               }       \
+               mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc);        \
+       } while (0)
+#else
+#define MOVING_GC_REGISTER(addr)
 #endif
 
 /*
@@ -8101,13 +8080,7 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
 
        klass->element_class = klass;
 
-#if HAVE_SGEN_GC
-       if (!reflection_info_desc) {
-               gsize bmap = 1;
-               reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);
-       }
-       mono_gc_register_root (&klass->reflection_info, sizeof (gpointer), reflection_info_desc);
-#endif
+       MOVING_GC_REGISTER (&klass->reflection_info);
        klass->reflection_info = tb;
 
        /* Put into cache so mono_class_get () will find it */
@@ -8172,9 +8145,7 @@ mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
                return;
 
        tb->generic_container = g_new0 (MonoGenericContainer, 1);
-       tb->generic_container->klass = klass;
-
-       tb->generic_container->context.container = tb->generic_container;
+       tb->generic_container->owner.klass = klass;
 }
 
 /*
@@ -8198,7 +8169,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;
 
@@ -8211,7 +8182,7 @@ mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
                g_assert (klass->generic_container->type_params [i].owner);
        }
 
-       klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
+       klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
 }
 
 /*
@@ -8477,27 +8448,24 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
        if (rmb->generic_params) {
                int count = mono_array_length (rmb->generic_params);
                MonoGenericContainer *container;
-               MonoGenericContext *context;
 
                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;
                }
 
-               context = &container->context;
-               context->container = container;
                if (klass->generic_container) {
                        container->parent = klass->generic_container;
-                       context->gclass = klass->generic_container->context.gclass;
+                       container->context.class_inst = klass->generic_container->context.class_inst;
                }
-               context->gmethod = mono_get_shared_generic_method (container);
+               container->context.gmethod = mono_get_shared_generic_method (container);
        }
 
        if (rmb->refs) {
@@ -8680,18 +8648,11 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
        MonoClass *klass;
        MonoReflectionTypeBuilder *tb = NULL;
        MonoGenericClass *gclass, *cached;
-       MonoInflatedGenericClass *igclass;
-       MonoDynamicGenericClass *dgclass = NULL;
        gboolean is_dynamic = FALSE;
        MonoDomain *domain;
        MonoType *geninst;
        int i;
 
-       klass = mono_class_from_mono_type (type->type);
-       if (!klass->generic_container && !klass->generic_class &&
-           !(klass->nested_in && klass->nested_in->generic_container))
-               return NULL;
-
        mono_loader_lock ();
 
        domain = mono_object_domain (type);
@@ -8708,22 +8669,30 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
                tb = (MonoReflectionTypeBuilder *) rgt;
 
                is_dynamic = TRUE;
-       } else if (klass->wastypebuilder) {
+       }
+
+       /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
+       if (tb && tb->generic_container)
+               mono_reflection_create_generic_class (tb);
+
+       klass = mono_class_from_mono_type (type->type);
+       if (!klass->generic_container) {
+               mono_loader_unlock ();
+               return NULL;
+       }
+
+       if (klass->wastypebuilder) {
                tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
 
                is_dynamic = TRUE;
        }
 
        if (is_dynamic) {
-               dgclass = g_new0 (MonoDynamicGenericClass, 1);
-               igclass = &dgclass->generic_class;
-               gclass = &igclass->generic_class;
+               MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
+               gclass = &dgclass->generic_class;
                gclass->is_dynamic = TRUE;
-               gclass->is_inflated = TRUE;
        } else {
-               igclass = g_new0 (MonoInflatedGenericClass, 1);
-               gclass = &igclass->generic_class;
-               gclass->is_inflated = TRUE;
+               gclass = g_new0 (MonoGenericClass, 1);
        }
 
        gclass->inst = g_new0 (MonoGenericInst, 1);
@@ -8746,50 +8715,6 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
 
        gclass->container_class = klass;
 
-       if (klass->generic_class) {
-               MonoGenericClass *kgclass = klass->generic_class;
-               MonoGenericClass *ogclass = gclass;
-
-               ogclass->context = g_new0 (MonoGenericContext, 1);
-               ogclass->context->container = gclass->container_class->generic_container;
-               ogclass->context->gclass = gclass;
-
-               if (is_dynamic) {
-                       dgclass = g_new0 (MonoDynamicGenericClass, 1);
-                       igclass = &dgclass->generic_class;
-                       gclass = &igclass->generic_class;
-                       gclass->is_dynamic = TRUE;
-                       gclass->is_inflated = TRUE;
-               } else {
-                       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, ogclass->context);
-
-                       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;
 
@@ -8803,10 +8728,6 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
 
        geninst->data.generic_class = gclass;
 
-       gclass->context = g_new0 (MonoGenericContext, 1);
-       gclass->context->container = gclass->container_class->generic_container;
-       gclass->context->gclass = gclass;
-
        mono_loader_unlock ();
 
        return geninst;
@@ -8817,7 +8738,6 @@ mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **ty
 {
        MonoClass *klass;
        MonoGenericClass *gclass, *cached;
-       MonoInflatedGenericClass *igclass;
        MonoType *geninst;
        int i;
 
@@ -8828,9 +8748,7 @@ mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **ty
 
        mono_loader_lock ();
 
-       igclass = g_new0 (MonoInflatedGenericClass, 1);
-       gclass = &igclass->generic_class;
-       gclass->is_inflated = TRUE;
+       gclass = g_new0 (MonoGenericClass, 1);
 
        gclass->inst = g_new0 (MonoGenericInst, 1);
        gclass->inst->type_argc = type_argc;
@@ -8856,13 +8774,7 @@ mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **ty
                MonoGenericClass *kgclass = klass->generic_class;
                MonoGenericClass *ogclass = gclass;
 
-               gclass->context = g_new0 (MonoGenericContext, 1);
-               gclass->context->container = gclass->container_class->generic_container;
-               gclass->context->gclass = gclass;
-
-               igclass = g_new0 (MonoInflatedGenericClass, 1);
-               gclass = &igclass->generic_class;
-               gclass->is_inflated = TRUE;
+               gclass = g_new0 (MonoGenericClass, 1);
 
                gclass->inst = g_new0 (MonoGenericInst, 1);
                gclass->inst->type_argc = kgclass->inst->type_argc;
@@ -8872,7 +8784,7 @@ mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **ty
                for (i = 0; i < gclass->inst->type_argc; i++) {
                        MonoType *t = kgclass->inst->type_argv [i];
 
-                       t = mono_class_inflate_generic_type (t, ogclass->context);
+                       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);
@@ -8900,10 +8812,6 @@ mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **ty
 
        geninst->data.generic_class = gclass;
 
-       gclass->context = g_new0 (MonoGenericContext, 1);
-       gclass->context->container = gclass->container_class->generic_container;
-       gclass->context->gclass = gclass;
-
        mono_loader_unlock ();
 
        return geninst;
@@ -8981,7 +8889,8 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
        ginst = mono_metadata_lookup_generic_inst (ginst);
 
        gmethod = g_new0 (MonoGenericMethod, 1);
-       gmethod->generic_class = method->klass->generic_class;
+       if (method->klass->generic_class)
+               gmethod->class_inst = method->klass->generic_class->inst;
        gmethod->container = container;
        gmethod->inst = ginst;
 
@@ -8992,11 +8901,11 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
                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->container = container;
-       context->gclass = method->klass->generic_class;
+       context->class_inst = gmethod->class_inst;
        context->gmethod = gmethod;
 
        if (method->is_inflated)
@@ -9012,42 +8921,29 @@ static MonoMethod *
 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
 {
        MonoGenericMethod *gmethod = NULL;
-       MonoInflatedGenericClass *gclass;
        MonoGenericContext *context;
        MonoClass *klass;
-       int i, n;
 
        klass = mono_class_from_mono_type (type->type.type);
-       gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
-       n = mono_method_signature (method)->generic_param_count;
+       g_assert (klass->generic_class);
+       context = mono_class_get_context (klass);
+
+       if (method->generic_container) {
+               g_assert (method->klass == klass->generic_class->container_class);
 
-       context = gclass->generic_class.context;
-       g_assert (context && context->container);
-       if (n) {
                gmethod = g_new0 (MonoGenericMethod, 1);
-               gmethod->generic_class = &gclass->generic_class;
+               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 == context->container);
+               gmethod->inst = method->generic_container->context.gmethod->inst;
 
                context = g_new0 (MonoGenericContext, 1);
-               context->container = gmethod->container;
-               context->gclass = &gclass->generic_class;
+               context->class_inst = klass->generic_class->inst;
                context->gmethod = gmethod;
        }
 
-       return mono_class_inflate_generic_method (method, context);
+       return mono_class_inflate_generic_method_full (method, klass, context);
 }
 
 static MonoMethod *
@@ -9136,13 +9032,14 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
 
                ifield = g_new0 (MonoInflatedField, 1);
                ifield->generic_type = field->type;
+               MOVING_GC_REGISTER (&ifield->reflection_info);
                ifield->reflection_info = obj;
 
                dgclass->fields [i] = *field;
                dgclass->fields [i].parent = klass;
                dgclass->fields [i].generic_info = ifield;
                dgclass->fields [i].type = mono_class_inflate_generic_type (
-                       field->type, dgclass->generic_class.generic_class.context);
+                       field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
        }
 
        for (i = 0; i < dgclass->count_properties; i++) {
@@ -9555,13 +9452,13 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam
                param->owner = gparam->tbuilder->generic_container;
        }
 
-       param->method = NULL;
        param->name = mono_string_to_utf8 (gparam->name);
        param->num = gparam->index;
 
        image = &gparam->tbuilder->module->dynamic_image->image;
        mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
 
+       MOVING_GC_REGISTER (&param->pklass->reflection_info);
        param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
 
        gparam->type.type = g_new0 (MonoType, 1);
@@ -9575,27 +9472,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;
+       SigBuffer buf;
 
-       MONO_ARCH_SAVE_REGS;
+       sigbuffer_init (&buf, 32);
 
-       p = buf = g_malloc (size = 50 + na * 50);
-
-       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;
 }
@@ -9605,26 +9498,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;
+       SigBuffer buf;
 
-       MONO_ARCH_SAVE_REGS;
-
-       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;
 }
@@ -9634,6 +9523,7 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
 {
        ReflectionMethodBuilder rmb;
        MonoMethodSignature *sig;
+       GSList *l;
        int i;
 
        sig = dynamic_method_to_signature (mb);
@@ -9651,13 +9541,35 @@ 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
+                        * NULL in the refs array, and fix it up later when the referenced 
+                        * DynamicMethod is created.
+                        */
+                       if (method->mhandle) {
+                               ref = method->mhandle;
+                       } else {
+                               ref = NULL;
+
+                               /* 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);
+                       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;
        }               
@@ -9665,6 +9577,22 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
        /* FIXME: class */
        mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &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] == NULL) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
+                               data [i + 1] = mb->mhandle;
+               }
+       }
+       g_slist_free (mb->referenced_by);
+
        g_free (rmb.refs);
 
        /* ilgen is no longer needed */