Tue Aug 21 16:40:04 CEST 2007 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / reflection.c
index 276e372b4a5a9043ae59517a26d586b36bf5c5c0..6a9a9fd8a383778c642be3cbd19652c1cf485d9b 100644 (file)
@@ -13,6 +13,7 @@
 #include "mono/metadata/tabledefs.h"
 #include "mono/metadata/metadata-internals.h"
 #include "mono/metadata/class-internals.h"
+#include "mono/metadata/gc-internal.h"
 #include "mono/metadata/tokentype.h"
 #include "mono/metadata/domain-internals.h"
 #include "mono/metadata/opcodes.h"
@@ -20,6 +21,7 @@
 #include "mono/metadata/object-internals.h"
 #include <mono/metadata/exception.h>
 #include <mono/metadata/marshal.h>
+#include <mono/metadata/security-manager.h>
 #include <stdio.h>
 #include <glib.h>
 #include <errno.h>
 #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
@@ -54,6 +62,7 @@ typedef struct {
        MonoObject *type;
        MonoString *name;
        MonoBoolean init_locals;
+       MonoBoolean skip_visibility;
        MonoArray *return_modreq;
        MonoArray *return_modopt;
        MonoArray *param_modreq;
@@ -63,7 +72,7 @@ typedef struct {
        guint32 nrefs;
        gpointer *refs;
        /* for PInvoke */
-       int charset, lasterr, native_cc;
+       int charset, extra_flags, native_cc;
        MonoString *dll, *dllentry;
 } ReflectionMethodBuilder;
 
@@ -135,11 +144,122 @@ 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 MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
+static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
+
+#define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
+#define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
+static CRITICAL_SECTION reflection_mutex;
+
+void
+mono_reflection_init (void)
+{
+       InitializeCriticalSection (&reflection_mutex);
+}
+
+static void
+sigbuffer_init (SigBuffer *buf, int size)
+{
+       buf->buf = g_malloc (size);
+       buf->p = buf->buf;
+       buf->end = buf->buf + size;
+}
+
+static void
+sigbuffer_make_room (SigBuffer *buf, int size)
+{
+       if (buf->end - buf->p < size) {
+               int new_size = buf->end - buf->buf + size + 32;
+               char *p = g_realloc (buf->buf, new_size);
+               size = buf->p - buf->buf;
+               buf->buf = p;
+               buf->p = p + size;
+               buf->end = buf->buf + new_size;
+       }
+}
+
+static void
+sigbuffer_add_value (SigBuffer *buf, guint32 val)
+{
+       sigbuffer_make_room (buf, 6);
+       mono_metadata_encode_value (val, buf->p, &buf->p);
+}
+
+static void
+sigbuffer_add_byte (SigBuffer *buf, guint8 val)
+{
+       sigbuffer_make_room (buf, 1);
+       buf->p [0] = val;
+       buf->p++;
+}
+
+static void
+sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
+{
+       sigbuffer_make_room (buf, size);
+       memcpy (buf->p, p, size);
+       buf->p += size;
+}
+
+static void
+sigbuffer_free (SigBuffer *buf)
+{
+       g_free (buf->buf);
+}
+
+/**
+ * mp_g_alloc:
+ *
+ * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
+ * from the C heap.
+ */
+static gpointer
+mp_g_malloc (MonoMemPool *mp, guint size)
+{
+       if (mp)
+               return mono_mempool_alloc (mp, size);
+       else
+               return g_malloc (size);
+}
+
+/**
+ * mp_g_alloc0:
+ *
+ * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
+ * from the C heap.
+ */
+static gpointer
+mp_g_malloc0 (MonoMemPool *mp, guint size)
+{
+       if (mp)
+               return mono_mempool_alloc0 (mp, size);
+       else
+               return g_malloc0 (size);
+}
+
+/**
+ * mp_string_to_utf8:
+ *
+ * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
+ * memory from the C heap.
+ */
+static char *
+mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
+{
+       if (mp)
+               return mono_string_to_utf8_mp (mp, s);
+       else
+               return mono_string_to_utf8 (s);
+}
+
+#define mp_g_new(mp,struct_type, n_structs)            \
+    ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
 
+#define mp_g_new0(mp,struct_type, n_structs)           \
+    ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
 
 static void
 alloc_table (MonoDynamicTable *table, guint nrows)
@@ -200,6 +320,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)
 {
@@ -284,7 +414,7 @@ add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int
        guint32 idx;
        char *copy;
        gpointer oldkey, oldval;
-       
+
        copy = g_malloc (s1+s2);
        memcpy (copy, b1, s1);
        memcpy (copy + s1, b2, s2);
@@ -299,6 +429,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.
@@ -426,7 +568,7 @@ default_class_from_mono_type (MonoType *type)
        case MONO_TYPE_STRING:
                return mono_defaults.string_class;
        default:
-               g_warning ("implement me 0x%02x\n", type->type);
+               g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
                g_assert_not_reached ();
        }
        
@@ -434,26 +576,25 @@ default_class_from_mono_type (MonoType *type)
 }
 
 static void
-encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
+encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
 {
        int i;
+       MonoGenericInst *class_inst;
 
-       if (!gclass) {
-               g_assert_not_reached ();
-               return;
-       }
+       g_assert (gclass);
 
-       mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
-       encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
-       mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
-       for (i = 0; i < gclass->inst->type_argc; ++i)
-               encode_type (assembly, gclass->inst->type_argv [i], p, &p);
+       class_inst = gclass->context.class_inst;
+
+       sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
+       encode_type (assembly, &gclass->container_class->byval_arg, buf);
+       sigbuffer_add_value (buf, class_inst->type_argc);
+       for (i = 0; i < class_inst->type_argc; ++i)
+               encode_type (assembly, class_inst->type_argv [i], buf);
 
-       *endbuf = p;
 }
 
 static void
-encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
+encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
 {
        if (!type) {
                g_assert_not_reached ();
@@ -461,7 +602,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:
@@ -482,58 +623,62 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
        case MONO_TYPE_STRING:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_TYPEDBYREF:
-               mono_metadata_encode_value (type->type, p, &p);
+               sigbuffer_add_value (buf, type->type);
                break;
        case MONO_TYPE_PTR:
-               mono_metadata_encode_value (type->type, p, &p);
-               encode_type (assembly, type->data.type, p, &p);
+               sigbuffer_add_value (buf, type->type);
+               encode_type (assembly, type->data.type, buf);
                break;
        case MONO_TYPE_SZARRAY:
-               mono_metadata_encode_value (type->type, p, &p);
-               encode_type (assembly, &type->data.klass->byval_arg, p, &p);
+               sigbuffer_add_value (buf, type->type);
+               encode_type (assembly, &type->data.klass->byval_arg, buf);
                break;
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_CLASS: {
                MonoClass *k = mono_class_from_mono_type (type);
-               mono_metadata_encode_value (type->type, p, &p);
+               /*
+                * Make sure we use the correct type.
+                */
+               sigbuffer_add_value (buf, k->byval_arg.type);
                /*
                 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
                 * otherwise two typerefs could point to the same type, leading to
                 * verification errors.
                 */
-               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;
        }
 
@@ -542,156 +687,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;
 }
 
@@ -701,32 +748,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 = 21 + nparams * 20 + notypes * 20;
        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;
@@ -736,24 +779,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;
 }
 
@@ -762,36 +802,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 = 10 + nl * 10;
-       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;
 
@@ -832,7 +866,8 @@ method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, g
        for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
                ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
                finally_start = ex_info->start + ex_info->len;
-               g_assert (ex_info->handlers);
+               if (!ex_info->handlers)
+                       continue;
                for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
                        ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
                        clause = &(clauses [clause_index]);
@@ -849,8 +884,10 @@ method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, g
                        if (ex_block->extype) {
                                clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
                        } else {
-                               /* FIXME: handle filters */
-                               clause->data.filter_offset = 0;
+                               if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
+                                       clause->data.filter_offset = ex_block->filter_offset;
+                               else
+                                       clause->data.filter_offset = 0;
                        }
                        finally_start = ex_block->start + ex_block->len;
 
@@ -873,8 +910,8 @@ method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
        gint maybe_small;
        guint32 fat_flags;
        char fat_header [12];
-       guint32 *intp;
-       guint16 *shortp;
+       guint32 int_value;
+       guint16 short_value;
        guint32 local_sig = 0;
        guint32 header_size = 12;
        MonoArray *code;
@@ -940,12 +977,12 @@ fat_header:
                fat_flags |= METHOD_HEADER_INIT_LOCALS;
        fat_header [0] = fat_flags;
        fat_header [1] = (header_size / 4 ) << 4;
-       shortp = (guint16*)(fat_header + 2);
-       *shortp = GUINT16_TO_LE (max_stack);
-       intp = (guint32*)(fat_header + 4);
-       *intp = GUINT32_TO_LE (code_size);
-       intp = (guint32*)(fat_header + 8);
-       *intp = GUINT32_TO_LE (local_sig);
+       short_value = GUINT16_TO_LE (max_stack);
+       memcpy (fat_header + 2, &short_value, 2);
+       int_value = GUINT32_TO_LE (code_size);
+       memcpy (fat_header + 4, &int_value, 4);
+       int_value = GUINT32_TO_LE (local_sig);
+       memcpy (fat_header + 8, &int_value, 4);
        idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
        /* add to the fixup todo list */
        if (mb->ilgen && mb->ilgen->num_token_fixups)
@@ -966,7 +1003,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) {
@@ -998,8 +1035,10 @@ fat_header:
                                        if (ex_block->extype) {
                                                val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
                                        } else {
-                                               /* FIXME: handle filters */
-                                               val = 0;
+                                               if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
+                                                       val = ex_block->filter_offset;
+                                               else
+                                                       val = 0;
                                        }
                                        val = GUINT32_TO_LE (val);
                                        mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
@@ -1034,12 +1073,49 @@ find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32
        return 0;
 }
 
+/* protected by reflection_mutex: 
+ * maps a mono runtime reflection handle to MonoCustomAttrInfo*
+ */
 static GHashTable *dynamic_custom_attrs = NULL;
 
+static MonoCustomAttrInfo*
+lookup_custom_attr (void *member)
+{
+       MonoCustomAttrInfo *ainfo, *res;
+       int size;
+
+       mono_reflection_lock ();
+       ainfo = g_hash_table_lookup (dynamic_custom_attrs, member);
+       mono_reflection_unlock ();
+
+       if (ainfo) {
+               /* Need to copy since it will be freed later */
+               size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
+               res = g_malloc0 (size);
+               memcpy (res, ainfo, size);
+               return res;
+       }
+       return NULL;
+}
+
+static gboolean
+custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
+{
+       /* FIXME: Need to do more checks */
+       if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
+               int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+
+               if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
+                       return FALSE;
+       }
+
+       return TRUE;
+}
+
 static MonoCustomAttrInfo*
 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
 {
-       int i, count;
+       int i, index, count, not_visible;
        MonoCustomAttrInfo *ainfo;
        MonoReflectionCustomAttr *cattr;
 
@@ -1049,17 +1125,34 @@ mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
 
        count = mono_array_length (cattrs);
 
+       /* Skip nonpublic attributes since MS.NET seems to do the same */
+       /* FIXME: This needs to be done more globally */
+       not_visible = 0;
+       for (i = 0; i < count; ++i) {
+               cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
+               if (!custom_attr_visible (image, cattr))
+                       not_visible ++;
+       }
+       count -= not_visible;
+
        ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
 
        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);
-               ainfo->attrs [i].ctor = cattr->ctor->method;
-               /* FIXME: might want to memdup the data here */
-               ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
-               ainfo->attrs [i].data_size = mono_array_length (cattr->data);
+               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;
+                       ainfo->attrs [index].data = saved;
+                       ainfo->attrs [index].data_size = mono_array_length (cattr->data);
+                       index ++;
+               }
        }
+       mono_loader_unlock ();
 
        return ainfo;
 }
@@ -1072,20 +1165,20 @@ 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
 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
 {
-       /* they are cached, so we don't free them */
-       if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
-               return;
-       g_free (ainfo);
+       if (!ainfo->cached)
+               g_free (ainfo);
 }
 
 /*
@@ -1193,7 +1286,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 */
@@ -1201,9 +1293,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);
@@ -1236,9 +1326,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;
                                }
@@ -1295,8 +1383,8 @@ reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, Mono
        rmb->refs = NULL;
 
        if (mb->dll) {
-               rmb->charset = mb->charset & 0xf;
-               rmb->lasterr = mb->charset & 0x40;
+               rmb->charset = mb->charset;
+               rmb->extra_flags = mb->extra_flags;
                rmb->native_cc = mb->native_cc;
                rmb->dllentry = mb->dllentry;
                rmb->dll = mb->dll;
@@ -1351,6 +1439,7 @@ reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, Mono
        rmb->name = mb->name;
        rmb->table_idx = NULL;
        rmb->init_locals = mb->init_locals;
+       rmb->skip_visibility = mb->skip_visibility;
        rmb->return_modreq = NULL;
        rmb->return_modopt = NULL;
        rmb->param_modreq = NULL;
@@ -1361,39 +1450,68 @@ reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, Mono
        rmb->refs = NULL;
 }      
 
+static void
+mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
+{
+       MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
+       MonoDynamicTable *table;
+       guint32 *values;
+       guint32 tok;
+
+       if (!mb->override_method)
+               return;
+
+       table = &assembly->tables [MONO_TABLE_METHODIMPL];
+       table->rows ++;
+       alloc_table (table, table->rows);
+       values = table->values + table->rows * MONO_METHODIMPL_SIZE;
+       values [MONO_METHODIMPL_CLASS] = tb->table_idx;
+       values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
+
+       tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
+       switch (mono_metadata_token_table (tok)) {
+       case MONO_TABLE_MEMBERREF:
+               tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
+               break;
+       case MONO_TABLE_METHOD:
+               tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
+               break;
+       default:
+               g_assert_not_reached ();
+       }
+       values [MONO_METHODIMPL_DECLARATION] = tok;
+}
+
 static void
 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
 {
        MonoDynamicTable *table;
        guint32 *values;
-       char *name;
        ReflectionMethodBuilder rmb;
        int i;
 
        reflection_methodbuilder_from_method_builder (&rmb, mb);
 
        mono_image_basic_method (&rmb, assembly);
+       mb->table_idx = *rmb.table_idx;
 
        if (mb->dll) { /* It's a P/Invoke method */
                guint32 moduleref;
-               int charset = mb->charset & 0xf;
-               int lasterr = mb->charset & 0x40;
-               int best_fit_mapping = mb->charset & 0x30;
-               int throw_on_unmappable = mb->charset & 0x3000;
+               /* map CharSet values to on-disk values */
+               int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
+               int extra_flags = mb->extra_flags;
                table = &assembly->tables [MONO_TABLE_IMPLMAP];
                table->rows ++;
                alloc_table (table, table->rows);
                values = table->values + table->rows * MONO_IMPLMAP_SIZE;
-               /* map CharSet values to on-disk values */
                
-               values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr | best_fit_mapping | throw_on_unmappable;
+               values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
                values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
-               name = mono_string_to_utf8 (mb->dllentry);
-               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);
+               if (mb->dllentry)
+                       values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
+               else
+                       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 ++;
@@ -1403,30 +1521,6 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *a
                }
        }
 
-       if (mb->override_method) {
-               MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
-               guint32 tok;
-               table = &assembly->tables [MONO_TABLE_METHODIMPL];
-               table->rows ++;
-               alloc_table (table, table->rows);
-               values = table->values + table->rows * MONO_METHODIMPL_SIZE;
-               values [MONO_METHODIMPL_CLASS] = tb->table_idx;
-               values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
-
-               tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
-               switch (mono_metadata_token_table (tok)) {
-               case MONO_TABLE_MEMBERREF:
-                       tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
-                       break;
-               case MONO_TABLE_METHOD:
-                       tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
-                       break;
-               default:
-                       g_assert_not_reached ();
-               }
-               values [MONO_METHODIMPL_DECLARATION] = tok;
-       }
-
        if (mb->generic_params) {
                table = &assembly->tables [MONO_TABLE_GENERICPARAM];
                table->rows += mono_array_length (mb->generic_params);
@@ -1449,25 +1543,13 @@ mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, Mon
        reflection_methodbuilder_from_ctor_builder (&rmb, mb);
 
        mono_image_basic_method (&rmb, assembly);
+       mb->table_idx = *rmb.table_idx;
 }
 
 static char*
-type_get_fully_qualified_name (MonoType *type) {
-       char *name, *result;
-       MonoClass *klass;
-       MonoAssembly *ta;
-
-       name = mono_type_get_name (type);
-       klass = my_mono_class_from_mono_type (type);
-       ta = klass->image->assembly;
-
-       result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
-               name, ta->aname.name,
-               ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
-               ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
-               ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
-       g_free (name);
-       return result;
+type_get_fully_qualified_name (MonoType *type)
+{
+       return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
 }
 
 static char*
@@ -1477,57 +1559,47 @@ type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
 
        klass = my_mono_class_from_mono_type (type);
        if (!klass) 
-               return mono_type_get_name (type);
+               return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
        ta = klass->image->assembly;
-       if (ta == ass || klass->image == mono_defaults.corlib)
-               return mono_type_get_name (type);
+       if (ta->dynamic || (ta == ass))
+               return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
 
-       return type_get_fully_qualified_name (type);
+       return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
 }
 
 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 (64);
+       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 < 64);
-       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 (64);
-       
-       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 < 64);
-       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;
 }
 
@@ -1538,6 +1610,12 @@ encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type)
        char *p, *box_val;
        char* buf;
        guint32 idx = 0, len = 0, dummy = 0;
+#ifdef ARM_FPU_FPA
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+       guint32 fpa_double [2];
+       guint32 *fpa_p;
+#endif
+#endif
        
        p = buf = g_malloc (64);
        if (!val) {
@@ -1567,8 +1645,18 @@ handle_enum:
                break;
        case MONO_TYPE_U8:
        case MONO_TYPE_I8:
+               len = 8;
+               break;
        case MONO_TYPE_R8:
                len = 8;
+#ifdef ARM_FPU_FPA
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+               fpa_p = (guint32*)box_val;
+               fpa_double [0] = fpa_p [1];
+               fpa_double [1] = fpa_p [0];
+               box_val = (char*)fpa_double;
+#endif
+#endif
                break;
        case MONO_TYPE_VALUETYPE:
                if (val->vtable->klass->enumtype) {
@@ -1599,6 +1687,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);
        }
@@ -1619,38 +1710,28 @@ handle_enum:
 
 static guint32
 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
-       char blob_size [64];
-       char *b = blob_size;
-       char *p, *buf, *str;
-       guint32 idx, len, bufsize = 256;
-       
-       p = buf = g_malloc (bufsize);
+       char *str;
+       SigBuffer buf;
+       guint32 idx, len;
 
-       mono_metadata_encode_value (minfo->type, p, &p);
+       sigbuffer_init (&buf, 32);
+
+       sigbuffer_add_value (&buf, minfo->type);
 
        switch (minfo->type) {
        case MONO_NATIVE_BYVALTSTR:
        case MONO_NATIVE_BYVALARRAY:
-               mono_metadata_encode_value (minfo->count, p, &p);
+               sigbuffer_add_value (&buf, minfo->count);
                break;
        case MONO_NATIVE_LPARRAY:
                if (minfo->eltype || minfo->has_size) {
-                       mono_metadata_encode_value (minfo->eltype, p, &p);
+                       sigbuffer_add_value (&buf, minfo->eltype);
                        if (minfo->has_size) {
-                               if (minfo->param_num != -1)
-                                       mono_metadata_encode_value (minfo->param_num, p, &p);
-                               else
-                                       mono_metadata_encode_value (0, p, &p);
-                               if (minfo->count != -1)
-                                       mono_metadata_encode_value (minfo->count, p, &p);
-                               else
-                                       mono_metadata_encode_value (0, p, &p);
+                               sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
+                               sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
 
                                /* LAMESPEC: ElemMult is undocumented */
-                               if (minfo->param_num != -1)
-                                       mono_metadata_encode_value (1, p, &p);
-                               else
-                                       mono_metadata_encode_value (0, p, &p);
+                               sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
                        }
                }
                break;
@@ -1658,69 +1739,43 @@ 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;
-                       g_free (str);
-               } else {
-                       mono_metadata_encode_value (0, p, &p);
-               }
-               if (minfo->marshaltype) {
-                       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 {
-                       mono_metadata_encode_value (0, p, &p);
-               }
-               if (minfo->marshaltyperef) {
-                       str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
+                       sigbuffer_add_value (&buf, 0);
+               }
+               /* native type name */
+               sigbuffer_add_value (&buf, 0);
+               /* custom marshaler type name */
+               if (minfo->marshaltype || minfo->marshaltyperef) {
+                       if (minfo->marshaltyperef)
+                               str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
+                       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 {
-                       mono_metadata_encode_value (0, p, &p);
+                       /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
+                       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;
 }
 
@@ -1729,7 +1784,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)
@@ -1738,9 +1792,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);
 
@@ -1773,9 +1825,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;
        }
@@ -1792,46 +1846,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;
 }
 
@@ -1840,7 +1886,6 @@ mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImag
 {
        MonoDynamicTable *table;
        guint32 *values;
-       char *name;
        guint num_methods = 0;
        guint32 semaidx;
 
@@ -1854,9 +1899,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);
 
@@ -1889,7 +1932,6 @@ mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *ass
 {
        MonoDynamicTable *table;
        guint32 *values;
-       char *name;
        guint num_methods = 0;
        guint32 semaidx;
 
@@ -1903,9 +1945,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);
 
@@ -1943,63 +1983,6 @@ mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *ass
        }
 }
 
-static void
-encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
-{
-       static MonoClass *NewConstraintAttr;
-       static MonoMethod *NewConstraintAttr_ctor;
-       MonoDynamicTable *table;
-       guint32 *values;
-       guint32 token, type;
-       char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
-       char *buf, *p;
-
-       if (!NewConstraintAttr)
-               NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib, 
-                       "System.Runtime.CompilerServices", "NewConstraintAttribute");
-       g_assert (NewConstraintAttr);
-
-       if (!NewConstraintAttr_ctor) {
-               NewConstraintAttr_ctor = mono_class_get_method_from_name (NewConstraintAttr, ".ctor", -1);
-               g_assert (NewConstraintAttr_ctor);
-       }
-
-       table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
-       table->rows += 1;
-       alloc_table (table, table->rows);
-
-       values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
-       owner <<= MONO_CUSTOM_ATTR_BITS;
-       owner |= MONO_CUSTOM_ATTR_GENERICPAR;
-       values [MONO_CUSTOM_ATTR_PARENT] = owner;
-
-       token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
-
-       type = mono_metadata_token_index (token);
-       type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
-       switch (mono_metadata_token_table (token)) {
-       case MONO_TABLE_METHOD:
-               type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
-               break;
-       case MONO_TABLE_MEMBERREF:
-               type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
-               break;
-       default:
-               g_warning ("got wrong token in custom attr");
-               return;
-       }
-       values [MONO_CUSTOM_ATTR_TYPE] = type;
-
-       buf = p = g_malloc (1);
-       mono_metadata_encode_value (4, p, &p);
-       g_assert (p-buf == 1);
-
-       values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
-
-       values += MONO_CUSTOM_ATTR_SIZE;
-       ++table->next_idx;
-}
-
 static void
 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
 {
@@ -2036,9 +2019,6 @@ encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynam
                values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
                        assembly, constraint->type);
        }
-
-       if (gparam->attrs &  GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
-               encode_new_constraint (assembly, owner);
 }
 
 static void
@@ -2055,7 +2035,11 @@ mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 o
 
        entry = g_new0 (GenericParamTableEntry, 1);
        entry->owner = owner;
-       entry->gparam = gparam;
+#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);
 }
@@ -2078,7 +2062,8 @@ write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *e
        values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
        values [MONO_GENERICPARAM_NUMBER] = param->num;
        values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
-       values [MONO_GENERICPARAM_KIND] = 0;
+
+       mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
 
        encode_constraints (entry->gparam, table_idx, assembly);
 }
@@ -2142,8 +2127,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;
        }
@@ -2159,11 +2144,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:
@@ -2172,29 +2155,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));
@@ -2399,42 +2384,35 @@ mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *
                return token;
        g_assert (f->field->parent);
        type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
-       token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg, 
+       token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg, 
                f->field->name,  fieldref_encode_signature (assembly, type));
        g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
        return token;
 }
 
 static guint32
-encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
+encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
 {
-       char *buf;
-       char *p;
+       SigBuffer buf;
        int i;
-       guint32 nparams =  gmethod->inst->type_argc;
-       guint32 size = 10 + nparams * 10;
+       guint32 nparams = context->method_inst->type_argc;
        guint32 idx;
-       char blob_size [6];
-       char *b = blob_size;
 
        if (!assembly->save)
                return 0;
 
-       p = buf = g_malloc (size);
+       sigbuffer_init (&buf, 32);
        /*
         * FIXME: vararg, explicit_this, differenc call_conv values...
         */
-       mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
-       mono_metadata_encode_value (nparams, p, &p);
+       sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
+       sigbuffer_add_value (&buf, nparams);
 
        for (i = 0; i < nparams; i++)
-               encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
+               encode_type (assembly, context->method_inst->type_argv [i], &buf);
 
-       /* store length */
-       g_assert (p - buf < size);
-       mono_metadata_encode_value (p-buf, b, &b);
-       idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
-       g_free (buf);
+       idx = sigbuffer_add_to_blob_cached (assembly, &buf);
+       sigbuffer_free (&buf);
        return idx;
 }
 
@@ -2450,7 +2428,7 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
        table = &assembly->tables [MONO_TABLE_METHODSPEC];
 
        g_assert (method->is_inflated);
-       method = mono_get_inflated_method (method);
+       g_assert (!method->klass->generic_container);
        imethod = (MonoMethodInflated *) method;
        declaring = imethod->declaring;
 
@@ -2471,7 +2449,7 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
                g_assert_not_reached ();
        }
 
-       sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
+       sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
 
        if (assembly->save) {
                alloc_table (table, table->rows + 1);
@@ -2487,29 +2465,28 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
 }
 
 static guint32
-mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
+mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
 {
        MonoMethodInflated *imethod;
        guint32 token;
        
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
+       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
        if (token)
                return token;
 
-       g_assert (m->is_inflated);
-       m = mono_get_inflated_method (m);
-       imethod = (MonoMethodInflated *) m;
+       g_assert (method->is_inflated);
+       imethod = (MonoMethodInflated *) method;
 
        if (mono_method_signature (imethod->declaring)->generic_param_count) {
-               token = method_encode_methodspec (assembly, m);
+               token = method_encode_methodspec (assembly, method);
        } else {
                guint32 sig = method_encode_signature (
                        assembly, mono_method_signature (imethod->declaring));
                token = mono_image_get_memberref_token (
-                       assembly, &m->klass->byval_arg, m->name, sig);
+                       assembly, &method->klass->byval_arg, method->name, sig);
        }
 
-       g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
+       g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
        return token;
 }
 
@@ -2533,10 +2510,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;
 
        /*
@@ -2549,31 +2523,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];
+
        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->typespec, tb->type.type, GUINT_TO_POINTER(token));
@@ -2624,13 +2600,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;
@@ -2645,7 +2618,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 */
@@ -2656,26 +2629,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;
 }
@@ -2930,7 +2900,7 @@ collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
 {
        int i;
 
-       g_ptr_array_add (types, type);
+       g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
 
        if (!type->subtypes)
                return;
@@ -3019,17 +2989,31 @@ type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
 }
 
 static void
-module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
+module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
+{
        int i;
        
-       mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
-       
-       /* no types in the module */
-       if (!mb->types)
-               return;
+       mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
+
+       if (moduleb->global_methods) {
+               for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
+                       MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
+                       mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
+                       params_add_cattrs (assembly, mb->pinfo);
+               }
+       }
+
+       if (moduleb->global_fields) {
+               for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
+                       MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
+                       mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
+               }
+       }
        
-       for (i = 0; i < mb->num_types; ++i)
-               type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
+       if (moduleb->types) {
+               for (i = 0; i < moduleb->num_types; ++i)
+                       type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
+       }
 }
 
 static void
@@ -3061,7 +3045,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 ++;
 }
 
@@ -3070,16 +3054,14 @@ 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;
+       table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
        table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
        table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
        table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
@@ -3168,6 +3150,44 @@ mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModu
        }
 }
 
+static void
+mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
+{
+       MonoDynamicTable *table;
+       MonoClass *klass;
+       guint32 *values;
+       guint32 scope, idx;
+       int i;
+
+       table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
+
+       if (assemblyb->type_forwarders) {
+               for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
+                       MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
+                       if (!t)
+                               continue;
+
+                       g_assert (t->type);
+
+                       klass = mono_class_from_mono_type (t->type);
+
+                       scope = resolution_scope_from_image (assembly, klass->image);
+                       g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
+                       idx = scope >> MONO_RESOLTION_SCOPE_BITS;
+
+                       table->rows++;
+                       alloc_table (table, table->rows);
+                       values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
+
+                       values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
+                       values [MONO_EXP_TYPE_TYPEDEF] = 0;
+                       values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
+                       values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
+                       values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
+               }
+       }
+}
+
 #define align_pointer(base,p)\
        do {\
                guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
@@ -3347,13 +3367,13 @@ 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 */
        int16val = (guint16*)p;
-       *int16val++ = GUINT16_TO_LE (1);
-       *int16val = GUINT16_TO_LE (1);
+       *int16val++ = GUINT16_TO_LE (meta->md_version_major);
+       *int16val = GUINT16_TO_LE (meta->md_version_minor);
        p += 8;
        /* version string */
        int32val = (guint32*)p;
@@ -3382,7 +3402,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);
        }
@@ -3390,16 +3410,16 @@ 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;
 
        if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
-                       (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
-                       (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
-               *p++ = 1; /* version */
-               *p++ = 1;
+           (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
+           (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
+               *p++ = 2; /* version */
+               *p++ = 0;
        } else {
                *p++ = 1; /* version */
                *p++ = 0;
@@ -3455,7 +3475,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) {
@@ -3513,7 +3533,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")) {
@@ -3623,48 +3643,11 @@ fixup_cattrs (MonoDynamicImage *assembly)
        }
 }
 
-/*
- * fixup_methodimpl:
- *
- * The METHODIMPL table might contain METHODDEF tokens whose final
- * value is not known when the table is emitted.
- */
-static void
-fixup_methodimpl (MonoDynamicImage *assembly)
-{
-       MonoDynamicTable *table;
-       guint32 *values;
-       guint32 decl, i, idx, token;
-       MonoObject *method;
-
-       table = &assembly->tables [MONO_TABLE_METHODIMPL];
-
-       for (i = 0; i < table->rows; ++i) {
-               values = table->values + ((i + 1) * MONO_METHODIMPL_SIZE);
-               decl = values [MONO_METHODIMPL_DECLARATION];
-
-               idx = decl >> MONO_METHODDEFORREF_BITS;
-               if ((decl & MONO_METHODDEFORREF_MASK) != MONO_METHODDEFORREF_METHODDEF)
-                       continue;
-
-               token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
-               method = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
-               g_assert (method);
-
-               if (!strcmp (method->vtable->klass->name, "MethodBuilder")) {
-                       token = mono_image_create_token (assembly, method, FALSE);
-                       idx = mono_metadata_token_index (token);
-                       values [MONO_METHODIMPL_DECLARATION] = (idx << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
-               }
-       }
-}
-
 static void
 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
 {
        MonoDynamicTable *table;
        guint32 *values;
-       char *name;
 
        table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
        table->rows++;
@@ -3672,9 +3655,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++;
 }
@@ -3705,18 +3686,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)
                        /* 
@@ -3774,10 +3764,20 @@ 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);
-
-       /* need to get the actual value from the key type... */
-       assembly->strong_name_size = 128;
+       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, 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) {
+               /* minimum key size (in 2.0) is 384 bits */
+               assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
+       } else {
+               /* FIXME - verifier */
+               g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
+               assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
+       }
        assembly->strong_name = g_malloc0 (assembly->strong_name_size);
 
        return token;
@@ -3791,7 +3791,6 @@ mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
        MonoReflectionAssemblyBuilder *assemblyb;
        MonoDomain *domain;
        guint32 *values;
-       char *name;
        int i;
        guint32 module_index;
 
@@ -3804,13 +3803,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, "");
        }
@@ -3844,6 +3839,8 @@ mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
                        mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
                }
        }
+       if (assemblyb->type_forwarders)
+               mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
 
        /* Emit MANIFESTRESOURCE table */
        module_index = 0;
@@ -3878,8 +3875,9 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
        MonoDynamicImage *assembly;
        MonoReflectionAssemblyBuilder *assemblyb;
        MonoDomain *domain;
+       GPtrArray *types;
        guint32 *values;
-       int i;
+       int i, j;
 
        assemblyb = moduleb->assemblyb;
        assembly = moduleb->dynamic_image;
@@ -3934,27 +3932,36 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
        alloc_table (table, 1);
        mono_image_fill_module_table (domain, moduleb, assembly);
 
-       /* Emit types */
-       {
-               /* Collect all types into a list sorted by their table_idx */
-               GPtrArray *types = g_ptr_array_new ();
+       /* Collect all types into a list sorted by their table_idx */
+       types = g_ptr_array_new ();
 
-               if (moduleb->types)
-                       for (i = 0; i < moduleb->num_types; ++i) {
-                               MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
-                               collect_types (types, type);
-                       }
+       if (moduleb->types)
+               for (i = 0; i < moduleb->num_types; ++i) {
+                       MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
+                       collect_types (types, type);
+               }
 
-               g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
-               table = &assembly->tables [MONO_TABLE_TYPEDEF];
-               table->rows += types->len;
-               alloc_table (table, table->rows);
+       g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
+       table = &assembly->tables [MONO_TABLE_TYPEDEF];
+       table->rows += types->len;
+       alloc_table (table, table->rows);
 
-               for (i = 0; i < types->len; ++i) {
-                       MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
-                       mono_image_get_type_info (domain, type, assembly);
-               }
-               g_ptr_array_free (types, TRUE);
+       /*
+        * Emit type names + namespaces at one place inside the string heap,
+        * so load_class_names () needs to touch fewer pages.
+        */
+       for (i = 0; i < types->len; ++i) {
+               MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
+               string_heap_insert_mstring (&assembly->sheap, tb->nspace);
+       }
+       for (i = 0; i < types->len; ++i) {
+               MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
+               string_heap_insert_mstring (&assembly->sheap, tb->name);
+       }
+
+       for (i = 0; i < types->len; ++i) {
+               MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
+               mono_image_get_type_info (domain, type, assembly);
        }
 
        /* 
@@ -3975,8 +3982,33 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
 
        /* fixup tokens */
        mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
+
+       /* Create the MethodImpl table.  We do this after emitting all methods so we already know
+        * the final tokens and don't need another fixup pass. */
+
+       if (moduleb->global_methods) {
+               for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
+                       MonoReflectionMethodBuilder *mb = mono_array_get (
+                               moduleb->global_methods, MonoReflectionMethodBuilder*, i);
+                       mono_image_add_methodimpl (assembly, mb);
+               }
+       }
+
+       for (i = 0; i < types->len; ++i) {
+               MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
+               if (type->methods) {
+                       for (j = 0; j < type->num_methods; ++j) {
+                               MonoReflectionMethodBuilder *mb = mono_array_get (
+                                       type->methods, MonoReflectionMethodBuilder*, j);
+
+                               mono_image_add_methodimpl (assembly, mb);
+                       }
+               }
+       }
+
+       g_ptr_array_free (types, TRUE);
+
        fixup_cattrs (assembly);
-       fixup_methodimpl (assembly);
 }
 
 /*
@@ -4188,7 +4220,7 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean c
                /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
        } else if (strcmp (klass->name, "MonoField") == 0) {
                MonoReflectionField *f = (MonoReflectionField *)obj;
-               if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
+               if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
                        static guint32 field_table_idx = 0xffffff;
                        field_table_idx --;
                        token = MONO_TOKEN_FIELD_DEF | field_table_idx;
@@ -4202,6 +4234,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);
        }
@@ -4224,7 +4260,7 @@ typedef struct {
        guint32 flags;
 } MonoILT;
 
-static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
+static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
 
 static MonoDynamicImage*
 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
@@ -4246,21 +4282,22 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c
        image->image.name = assembly_name;
        image->image.assembly_name = image->image.name; /* they may be different */
        image->image.module_name = module_name;
-       image->image.version = version;
+       image->image.version = g_strdup (version);
+       image->image.md_version_major = 1;
+       image->image.md_version_minor = 1;
        image->image.dynamic = TRUE;
-       image->image.ref_count = 1;
 
        image->image.references = g_new0 (MonoAssembly*, 1);
        image->image.references [0] = NULL;
 
        mono_image_init (&image->image);
 
-       image->token_fixups = mono_g_hash_table_new (NULL, NULL);
+       image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
        image->method_to_table_idx = g_hash_table_new (NULL, NULL);
        image->field_to_table_idx = g_hash_table_new (NULL, NULL);
        image->method_aux_hash = g_hash_table_new (NULL, NULL);
        image->handleref = g_hash_table_new (NULL, NULL);
-       image->tokens = mono_g_hash_table_new (NULL, NULL);
+       image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
        image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
        image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
        image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
@@ -4271,7 +4308,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 */
@@ -4331,6 +4368,24 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
        else
                assembly->assembly.aname.culture = g_strdup ("");
 
+        if (assemblyb->version) {
+                       char *vstr = mono_string_to_utf8 (assemblyb->version);
+                       char **version = g_strsplit (vstr, ".", 4);
+                       char **parts = version;
+                       assembly->assembly.aname.major = atoi (*parts++);
+                       assembly->assembly.aname.minor = atoi (*parts++);
+                       assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
+                       assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
+
+                       g_strfreev (version);
+                       g_free (vstr);
+        } else {
+                       assembly->assembly.aname.major = 0;
+                       assembly->assembly.aname.minor = 0;
+                       assembly->assembly.aname.build = 0;
+                       assembly->assembly.aname.revision = 0;
+        }
+
        assembly->run = assemblyb->access != 2;
        assembly->save = assemblyb->access != 1;
 
@@ -4339,9 +4394,9 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
        assembly->assembly.aname.name = image->image.name;
        assembly->assembly.image = &image->image;
 
-       mono_domain_lock (domain);
+       mono_domain_assemblies_lock (domain);
        domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
-       mono_domain_unlock (domain);
+       mono_domain_assemblies_unlock (domain);
 
        register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
        mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
@@ -4415,6 +4470,7 @@ resource_tree_create (MonoArray *win32_resources)
 
                /* Create node */
 
+               /* FIXME: BUG: this stores managed references in unmanaged memory */
                lang_node = g_new0 (ResTreeNode, 1);
                lang_node->id = win32_res->lang_id;
                lang_node->win32_res = win32_res;
@@ -4570,7 +4626,7 @@ assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssembly
 
        resource_tree_encode (tree, p, p, &p);
 
-       g_assert (p - buf < size);
+       g_assert (p - buf <= size);
 
        assembly->win32_res = g_malloc (p - buf);
        assembly->win32_res_size = p - buf;
@@ -4674,7 +4730,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));
@@ -4823,7 +4879,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);
@@ -4864,7 +4920,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)
@@ -4894,7 +4950,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;
@@ -4965,7 +5021,7 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
 }
 
 MonoReflectionModule *
-mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
+mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
 {
        char *name;
        MonoImage *image;
@@ -4973,11 +5029,12 @@ mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
        MonoDynamicAssembly *assembly;
        guint32 module_count;
        MonoImage **new_modules;
+       gboolean *new_modules_loaded;
        
        name = mono_string_to_utf8 (fileName);
 
        image = mono_image_open (name, &status);
-       if (status) {
+       if (!image) {
                MonoException *exc;
                if (status == MONO_IMAGE_ERROR_ERRNO)
                        exc = mono_get_exception_file_not_found (fileName);
@@ -4994,13 +5051,19 @@ mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
 
        module_count = image->assembly->image->module_count;
        new_modules = g_new0 (MonoImage *, module_count + 1);
+       new_modules_loaded = g_new0 (gboolean, module_count + 1);
 
        if (image->assembly->image->modules)
                memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
+       if (image->assembly->image->modules_loaded)
+               memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
        new_modules [module_count] = image;
+       new_modules_loaded [module_count] = TRUE;
+       mono_image_addref (image);
 
        g_free (image->assembly->image->modules);
        image->assembly->image->modules = new_modules;
+       image->assembly->image->modules_loaded = new_modules_loaded;
        image->assembly->image->module_count ++;
 
        mono_assembly_load_references (image, &status);
@@ -5034,7 +5097,7 @@ reflected_equal (gconstpointer a, gconstpointer b) {
 static guint
 reflected_hash (gconstpointer a) {
        const ReflectedEntry *ea = a;
-       return GPOINTER_TO_UINT (ea->item);
+       return mono_aligned_addr_hash (ea->item);
 }
 
 #define CHECK_OBJECT(t,p,k)    \
@@ -5045,42 +5108,53 @@ reflected_hash (gconstpointer a) {
                e.refclass = (k);       \
                mono_domain_lock (domain);      \
                if (!domain->refobject_hash)    \
-                       domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);       \
+                       domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
                if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
                        mono_domain_unlock (domain);    \
                        return _obj;    \
                }       \
+        mono_domain_unlock (domain); \
        } while (0)
 
 #if HAVE_BOEHM_GC
 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
+#elif HAVE_SGEN_GC
+#define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
 #else
 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
 #endif
 
-#define CACHE_OBJECT(p,o,k)    \
+#define CACHE_OBJECT(t,p,o,k)  \
        do {    \
-               ReflectedEntry *e = ALLOC_REFENTRY;     \
-               e->item = (p);  \
-               e->refclass = (k);      \
-               mono_g_hash_table_insert (domain->refobject_hash, e,o); \
+               t _obj; \
+        ReflectedEntry pe; \
+        pe.item = (p); \
+        pe.refclass = (k); \
+        mono_domain_lock (domain); \
+               if (!domain->refobject_hash)    \
+                       domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
+        _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
+        if (!_obj) { \
+                   ReflectedEntry *e = ALLOC_REFENTRY;         \
+                   e->item = (p);      \
+                   e->refclass = (k);  \
+                   mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
+            _obj = o; \
+        } \
                mono_domain_unlock (domain);    \
+        return _obj; \
        } while (0)
 
-static void 
+static gpointer
 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
 {
-       /* this is done only once */
-       mono_domain_lock (domain);
-       CACHE_OBJECT (assembly, res, NULL);
+       CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
 }
 
-static void
+static gpointer
 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
 {
-       /* this is done only once */
-       mono_domain_lock (domain);
-       CACHE_OBJECT (module, res, NULL);
+       CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
 }
 
 void
@@ -5112,6 +5186,7 @@ mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
                if (ass->modules)
                        memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
                new_modules [module_count] = &image->image;
+               mono_image_addref (&image->image);
 
                g_free (ass->modules);
                ass->modules = new_modules;
@@ -5139,8 +5214,7 @@ mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
        res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
        res->assembly = assembly;
 
-       CACHE_OBJECT (assembly, res, NULL);
-       return res;
+       CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
 }
 
 
@@ -5159,11 +5233,12 @@ mono_module_get_object   (MonoDomain *domain, MonoImage *image)
        res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
 
        res->image = image;
-       res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
+       MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
 
-       res->fqname    = mono_string_new (domain, image->name);
-       res->name      = mono_string_new (domain, basename = g_path_get_basename (image->name));
-       res->scopename = mono_string_new (domain, image->module_name);
+       MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
+       basename = g_path_get_basename (image->name);
+       MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
+       MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
        
        g_free (basename);
 
@@ -5171,19 +5246,17 @@ 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);
        }
 
-       mono_image_addref (image);
-
-       CACHE_OBJECT (image, res, NULL);
-       return res;
+       CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
 }
 
 MonoReflectionModule*   
@@ -5206,8 +5279,8 @@ mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_ind
        g_assert (table_index < table->rows);
        mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
 
-       res->image = 0;
-       res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
+       res->image = NULL;
+       MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
        name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
 
        /* Check whenever the row has a corresponding row in the moduleref table */
@@ -5219,9 +5292,9 @@ mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_ind
                        res->image = image->modules [i];
        }
 
-       res->fqname    = mono_string_new (domain, name);
-       res->name      = mono_string_new (domain, name);
-       res->scopename = mono_string_new (domain, name);
+       MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
+       MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
+       MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
        res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
        res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
 
@@ -5267,13 +5340,16 @@ mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
                return t1->data.array->eklass == t2->data.array->eklass;
        case MONO_TYPE_GENERICINST: {
                int i;
-               if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
+               MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
+               MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
+               if (i1->type_argc != i2->type_argc)
                        return FALSE;
                if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
                                               &t2->data.generic_class->container_class->byval_arg))
                        return FALSE;
-               for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
-                       if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
+               /* FIXME: we should probably just compare the instance pointers directly.  */
+               for (i = 0; i < i1->type_argc; ++i) {
+                       if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
                                return FALSE;
                }
                return TRUE;
@@ -5305,6 +5381,17 @@ mymono_metadata_type_hash (MonoType *t1)
                return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
        case MONO_TYPE_PTR:
                return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
+       case MONO_TYPE_GENERICINST: {
+               int i;
+               MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
+               hash += g_str_hash (t1->data.generic_class->container_class->name);
+               hash *= 13;
+               for (i = 0; i < inst->type_argc; ++i) {
+                       hash += mymono_metadata_type_hash (inst->type_argv [i]);
+                       hash *= 13;
+               }
+               return hash;
+       }
        }
        return hash;
 }
@@ -5314,8 +5401,7 @@ mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
 {
        static MonoClass *System_Reflection_MonoGenericClass;
        MonoReflectionGenericClass *res;
-       MonoGenericClass *gclass;
-       MonoClass *gklass;
+       MonoClass *klass, *gklass;
 
        if (!System_Reflection_MonoGenericClass) {
                System_Reflection_MonoGenericClass = mono_class_from_name (
@@ -5323,22 +5409,56 @@ mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
                g_assert (System_Reflection_MonoGenericClass);
        }
 
-       gclass = geninst->data.generic_class;
-       gklass = gclass->container_class;
+       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)
-               res->generic_type = gklass->reflection_info;
+               MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
        else
-               res->generic_type = mono_type_get_object (domain, &gclass->container_class->byval_arg);
+               MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
 
        return res;
 }
 
+static gboolean
+verify_safe_for_managed_space (MonoType *type)
+{
+       switch (type->type) {
+#ifdef DEBUG_HARDER
+       case MONO_TYPE_ARRAY:
+               return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
+       case MONO_TYPE_PTR:
+               return verify_safe_for_managed_space (type->data.type);
+       case MONO_TYPE_SZARRAY:
+               return verify_safe_for_managed_space (&type->data.klass->byval_arg);
+       case MONO_TYPE_GENERICINST: {
+               MonoGenericInst *inst = type->data.generic_class->inst;
+               int i;
+               if (!inst->is_open)
+                       break;
+               for (i = 0; i < inst->type_argc; ++i)
+                       if (!verify_safe_for_managed_space (inst->type_argv [i]))
+                               return FALSE;
+               break;
+       }
+#endif
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR:
+               return TRUE;
+       }
+       return TRUE;
+}
+
 /*
  * mono_type_get_object:
  * @domain: an app domain
@@ -5354,8 +5474,8 @@ mono_type_get_object (MonoDomain *domain, MonoType *type)
 
        mono_domain_lock (domain);
        if (!domain->type_hash)
-               domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
-                               (GCompareFunc)mymono_metadata_type_equal);
+               domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
+                               (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
        if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
                mono_domain_unlock (domain);
                return res;
@@ -5366,6 +5486,12 @@ mono_type_get_object (MonoDomain *domain, MonoType *type)
                mono_domain_unlock (domain);
                return res;
        }
+
+       if (!verify_safe_for_managed_space (type)) {
+               mono_domain_unlock (domain);
+               mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
+       }
+
        if (klass->reflection_info && !klass->wastypebuilder) {
                /* g_assert_not_reached (); */
                /* should this be considered an error condition? */
@@ -5375,7 +5501,11 @@ mono_type_get_object (MonoDomain *domain, MonoType *type)
                }
        }
        mono_class_init (klass);
+#ifdef HAVE_SGEN_GC
+       res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
+#else
        res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
+#endif
        res->type = type;
        mono_g_hash_table_insert (domain->type_hash, type, res);
        mono_domain_unlock (domain);
@@ -5397,7 +5527,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;
 
@@ -5406,36 +5539,41 @@ 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") || !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;
-               gret->method.name = mono_string_new (domain, method->name);
-               gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
-               CACHE_OBJECT (method, gret, refclass);
-               return (MonoReflectionMethod *) gret;
+               MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
+               MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
+               CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
        }
 
        if (!refclass)
                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;
-       ret->name = mono_string_new (domain, method->name);
-       ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
-       CACHE_OBJECT (method, ret, refclass);
-       return ret;
+       MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
+       MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
+       CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
 }
 
 /*
@@ -5451,21 +5589,21 @@ MonoReflectionField*
 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
 {
        MonoReflectionField *res;
-       MonoClass *oklass;
+       static MonoClass *monofield_klass;
 
        CHECK_OBJECT (MonoReflectionField *, field, klass);
-       oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
-       res = (MonoReflectionField *)mono_object_new (domain, oklass);
+       if (!monofield_klass)
+               monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
+       res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
        res->klass = klass;
        res->field = field;
-       res->name = mono_string_new (domain, field->name);
+       MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
        if (field->generic_info)
                res->attrs = field->generic_info->generic_type->attrs;
        else
                res->attrs = field->type->attrs;
-       res->type = mono_type_get_object (domain, field->type);
-       CACHE_OBJECT (field, res, klass);
-       return res;
+       MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
+       CACHE_OBJECT (MonoReflectionField *, field, res, klass);
 }
 
 /*
@@ -5481,15 +5619,15 @@ MonoReflectionProperty*
 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
 {
        MonoReflectionProperty *res;
-       MonoClass *oklass;
+       static MonoClass *monoproperty_klass;
 
        CHECK_OBJECT (MonoReflectionProperty *, property, klass);
-       oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
-       res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
+       if (!monoproperty_klass)
+               monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
+       res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
        res->klass = klass;
        res->property = property;
-       CACHE_OBJECT (property, res, klass);
-       return res;
+       CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
 }
 
 /*
@@ -5505,15 +5643,15 @@ MonoReflectionEvent*
 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
 {
        MonoReflectionEvent *res;
-       MonoClass *oklass;
+       static MonoClass *monoevent_klass;
 
        CHECK_OBJECT (MonoReflectionEvent *, event, klass);
-       oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
-       res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
+       if (!monoevent_klass)
+               monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
+       res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
        res->klass = klass;
        res->event = event;
-       CACHE_OBJECT (event, res, klass);
-       return res;
+       CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
 }
 
 /*
@@ -5536,6 +5674,7 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
        MonoType *type = NULL;
        MonoObject *dbnull = mono_get_dbnull_object (domain);
        MonoMarshalSpec **mspecs;
+       MonoMethodSignature *sig;
        int i;
 
        if (!System_Reflection_ParameterInfo)
@@ -5550,29 +5689,30 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
         */
        CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
 
+       sig = mono_method_signature (method);
        member = mono_method_get_object (domain, method, NULL);
-       names = g_new (char *, mono_method_signature (method)->param_count);
+       names = g_new (char *, sig->param_count);
        mono_method_get_param_names (method, (const char **) names);
 
-       mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
+       mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
        mono_method_get_marshal_info (method, mspecs);
 
-       res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
-       for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
+       res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
+       for (i = 0; i < sig->param_count; ++i) {
                param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
-               param->ClassImpl = mono_type_get_object (domain, mono_method_signature (method)->params [i]);
-               param->MemberImpl = (MonoObject*)member;
-               param->NameImpl = mono_string_new (domain, names [i]);
+               MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
+               MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
+               MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
                param->PositionImpl = i;
-               param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
+               param->AttrsImpl = sig->params [i]->attrs;
 
                if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
-                       param->DefaultValueImpl = dbnull;
+                       MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
                } else {
 
                        if (!blobs) {
-                               blobs = g_new0 (char *, mono_method_signature (method)->param_count);
-                               types = g_new0 (guint32, mono_method_signature (method)->param_count);
+                               blobs = g_new0 (char *, sig->param_count);
+                               types = g_new0 (guint32, sig->param_count);
                                get_default_param_value_blobs (method, blobs, types); 
                        }
 
@@ -5583,21 +5723,26 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
                        type->data.klass = NULL;
                        if (types [i] == MONO_TYPE_CLASS)
                                type->data.klass = mono_defaults.object_class;
-                       else    
+                       else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
+                               /* For enums, types [i] contains the base type */
+
+                                       type->type = MONO_TYPE_VALUETYPE;
+                                       type->data.klass = mono_class_from_mono_type (sig->params [i]);
+                       } else
                                type->data.klass = mono_class_from_mono_type (type);
-                       
-                       param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
+
+                       MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
 
                        /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
                        if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) 
-                               param->DefaultValueImpl = dbnull;
+                               MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
                        
                }
 
                if (mspecs [i + 1])
-                       param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
+                       MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
                
-               mono_array_set (res, gpointer, i, param);
+               mono_array_setref (res, i, param);
        }
        g_free (names);
        g_free (blobs);
@@ -5609,8 +5754,7 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
                        mono_metadata_free_marshal_spec (mspecs [i]);
        g_free (mspecs);
        
-       CACHE_OBJECT (&(method->signature), res, NULL);
-       return res;
+       CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
 }
 
 /*
@@ -5676,21 +5820,21 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
        ret->init_locals = header->init_locals;
        ret->max_stack = header->max_stack;
        ret->local_var_sig_token = local_var_sig_token;
-       ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
-       memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
+       MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
+       memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
 
        /* Locals */
-       ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
+       MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
        for (i = 0; i < header->num_locals; ++i) {
                MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
-               info->local_type = mono_type_get_object (domain, header->locals [i]);
+               MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
                info->is_pinned = header->locals [i]->pinned;
                info->local_index = i;
-               mono_array_set (ret->locals, MonoReflectionLocalVariableInfo*, i, info);
+               mono_array_setref (ret->locals, i, info);
        }
 
        /* Exceptions */
-       ret->clauses = mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses);
+       MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
        for (i = 0; i < header->num_clauses; ++i) {
                MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
                MonoExceptionClause *clause = &header->clauses [i];
@@ -5703,12 +5847,12 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
                if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
                        info->filter_offset = clause->data.filter_offset;
                else if (clause->data.catch_class)
-                       info->catch_type = mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg);
+                       MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
 
-               mono_array_set (ret->clauses, MonoReflectionExceptionHandlingClause*, i, info);
+               mono_array_setref (ret->clauses, i, info);
        }
 
-       CACHE_OBJECT (method, ret, NULL);
+       CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
        return ret;
 }
 
@@ -5716,13 +5860,13 @@ MonoObject *
 mono_get_dbnull_object (MonoDomain *domain)
 {
        MonoObject *obj;
-       MonoClass *klass;
        static MonoClassField *dbnull_value_field = NULL;
        
        if (!dbnull_value_field) {
-               klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
-               mono_class_init (klass);
-               dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
+               MonoClass *dbnull_klass;
+               dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
+               mono_class_init (dbnull_klass);
+               dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
                g_assert (dbnull_value_field);
        }
        obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
@@ -5749,14 +5893,13 @@ get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
        if (!methodsig->param_count)
                return;
 
-       if (klass->generic_class) {
-               return; /* FIXME - ??? */
-       }
-
        mono_class_init (klass);
 
        if (klass->image->dynamic) {
-               MonoReflectionMethodAux *aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
+               MonoReflectionMethodAux *aux;
+               if (method->is_inflated)
+                       method = ((MonoMethodInflated*)method)->declaring;
+               aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
                if (aux && aux->param_defaults) {
                        memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
                        memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
@@ -5890,7 +6033,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 != ',')
@@ -5923,12 +6066,13 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
  *
  * Returns: 0 on parse error.
  */
-int
-mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
-
-       char *start, *p, *w, *last_point, *startn;
+static int
+_mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
+                            MonoTypeNameParse *info)
+{
+       char *start, *p, *w, *temp, *last_point, *startn;
        int in_modifiers = 0;
-       int isbyref = 0, rank;
+       int isbyref = 0, rank, arity = 0, i;
 
        start = p = w = name;
 
@@ -5936,6 +6080,7 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
        info->name = info->name_space = NULL;
        info->nested = NULL;
        info->modifiers = NULL;
+       info->type_arguments = NULL;
 
        /* last_point separates the namespace from the name */
        last_point = NULL;
@@ -5959,7 +6104,7 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
                        }
                        break;
                case '.':
-                       last_point = w;
+                       last_point = p;
                        break;
                case '\\':
                        ++p;
@@ -5968,14 +6113,24 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
                case '*':
                case '[':
                case ',':
+               case ']':
                        in_modifiers = 1;
                        break;
+               case '`':
+                       ++p;
+                       i = strtol (p, &temp, 10);
+                       arity += i;
+                       if (p == temp)
+                               return 0;
+                       p = temp-1;
+                       break;
                default:
                        break;
                }
                if (in_modifiers)
                        break;
-               *w++ = *p++;
+               // *w++ = *p++;
+               p++;
        }
        
        if (!info->name) {
@@ -6002,6 +6157,63 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
                        *p++ = 0;
                        break;
                case '[':
+                       if (arity != 0) {
+                               *p++ = 0;
+                               info->type_arguments = g_ptr_array_new ();
+                               for (i = 0; i < arity; i++) {
+                                       MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
+                                       gboolean fqname = FALSE;
+
+                                       g_ptr_array_add (info->type_arguments, subinfo);
+
+                                       if (*p == '[') {
+                                               p++;
+                                               fqname = TRUE;
+                                       }
+
+                                       if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
+                                               return 0;
+
+                                       if (fqname) {
+                                               char *aname;
+
+                                               if (*p != ',')
+                                                       return 0;
+                                               *p++ = 0;
+
+                                               aname = p;
+                                               while (*p && (*p != ']'))
+                                                       p++;
+
+                                               if (*p != ']')
+                                                       return 0;
+
+                                               *p++ = 0;
+                                               while (*aname) {
+                                                       if (g_ascii_isspace (*aname)) {
+                                                               ++aname;
+                                                               continue;
+                                                       }
+                                                       break;
+                                               }
+                                               if (!*aname ||
+                                                   !assembly_name_to_aname (&subinfo->assembly, aname))
+                                                       return 0;
+                                       }
+
+                                       if (i + 1 < arity) {
+                                               if (*p != ',')
+                                                       return 0;
+                                       } else {
+                                               if (*p != ']')
+                                                       return 0;
+                                       }
+                                       *p++ = 0;
+                               }
+
+                               arity = 0;
+                               break;
+                       }
                        rank = 1;
                        *p++ = 0;
                        while (*p) {
@@ -6017,7 +6229,13 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
                                return 0;
                        info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
                        break;
+               case ']':
+                       if (is_recursed)
+                               goto end;
+                       return 0;
                case ',':
+                       if (is_recursed)
+                               goto end;
                        *p++ = 0;
                        while (*p) {
                                if (g_ascii_isspace (*p)) {
@@ -6033,20 +6251,57 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
                        break;
                default:
                        return 0;
-                       break;
                }
                if (info->assembly.name)
                        break;
        }
-       *w = 0; /* terminate class name */
+       // *w = 0; /* terminate class name */
+ end:
        if (!info->name || !*info->name)
                return 0;
+       if (endptr)
+               *endptr = p;
        /* add other consistency checks */
        return 1;
 }
 
+int
+mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
+{
+       return _mono_reflection_parse_type (name, NULL, FALSE, info);
+}
+
 static MonoType*
-mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
+_mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
+{
+       gboolean type_resolve = FALSE;
+       MonoType *type;
+       MonoImage *rootimage = image;
+
+       if (info->assembly.name) {
+               MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
+               if (!assembly) {
+                       /* then we must load the assembly ourselve - see #60439 */
+                       assembly = mono_assembly_load (&info->assembly, NULL, NULL);
+                       if (!assembly)
+                               return NULL;
+               }
+               image = assembly->image;
+       } else if (!image) {
+               image = mono_defaults.corlib;
+       }
+
+       type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
+       if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
+               image = mono_defaults.corlib;
+               type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
+       }
+
+       return type;
+}
+
+static MonoType*
+mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
 {
        MonoClass *klass;
        GList *mod;
@@ -6085,6 +6340,36 @@ mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gb
        if (!klass)
                return NULL;
        mono_class_init (klass);
+
+       if (info->type_arguments) {
+               MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
+               MonoReflectionType *the_type;
+               MonoType *instance;
+               int i;
+
+               for (i = 0; i < info->type_arguments->len; i++) {
+                       MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
+
+                       type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
+                       if (!type_args [i]) {
+                               g_free (type_args);
+                               return NULL;
+                       }
+               }
+
+               the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
+
+               instance = mono_reflection_bind_generic_parameters (
+                       the_type, info->type_arguments->len, type_args);
+
+               if (!instance) {
+                       g_free (type_args);
+                       return NULL;
+               }
+
+               klass = mono_class_from_mono_type (instance);
+       }
+
        for (mod = info->modifiers; mod; mod = mod->next) {
                modval = GPOINTER_TO_UINT (mod->data);
                if (!modval) { /* byref: must be last modifier */
@@ -6112,14 +6397,19 @@ mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gb
  */
 
 MonoType*
-mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
+mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
+       return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
+}
+       
+MonoType*
+mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
 {
        MonoType *type;
        MonoReflectionAssembly *assembly;
        GString *fullName;
        GList *mod;
 
-       type = mono_reflection_get_type_internal (image, info, ignorecase);
+       type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
        if (type)
                return type;
        if (!mono_domain_has_type_resolve (mono_domain_get ()))
@@ -6152,7 +6442,7 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
                        if (abuilder->modules) {
                                for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
                                        MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
-                                       type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
+                                       type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
                                        if (type)
                                                break;
                                }
@@ -6161,20 +6451,39 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
                        if (!type && abuilder->loaded_modules) {
                                for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
                                        MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
-                                       type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
+                                       type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
                                        if (type)
                                                break;
                                }
                        }
                }
                else
-                       type = mono_reflection_get_type_internal (assembly->assembly->image, 
+                       type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
                                                                                                          info, ignorecase);
        }
        g_string_free (fullName, TRUE);
        return type;
 }
 
+static void
+free_type_info (MonoTypeNameParse *info)
+{
+       g_list_free (info->modifiers);
+       g_list_free (info->nested);
+
+       if (info->type_arguments) {
+               int i;
+
+               for (i = 0; i < info->type_arguments->len; i++) {
+                       MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
+
+                       free_type_info (subinfo);
+               }
+
+               g_ptr_array_free (info->type_arguments, TRUE);
+       }
+}
+
 /*
  * mono_reflection_type_from_name:
  * @name: type name.
@@ -6188,49 +6497,20 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
 MonoType*
 mono_reflection_type_from_name (char *name, MonoImage *image)
 {
-       MonoType *type;
+       MonoType *type = NULL;
        MonoTypeNameParse info;
-       MonoAssembly *assembly;
        char *tmp;
-       gboolean type_resolve = FALSE;
 
        /* Make a copy since parse_type modifies its argument */
        tmp = g_strdup (name);
        
        /*g_print ("requested type %s\n", str);*/
-       if (!mono_reflection_parse_type (tmp, &info)) {
-               g_free (tmp);
-               g_list_free (info.modifiers);
-               g_list_free (info.nested);
-               return NULL;
-       }
-
-       if (info.assembly.name) {
-               assembly = mono_assembly_loaded (&info.assembly);
-               if (!assembly) {
-                       /* then we must load the assembly ourselve - see #60439 */
-                       assembly = mono_assembly_load (&info.assembly, NULL, NULL);
-                       if (!assembly) {
-                               g_free (tmp);
-                               g_list_free (info.modifiers);
-                               g_list_free (info.nested);
-                               return NULL;
-                       }
-               }
-               image = assembly->image;
-       } else if (image == NULL) {
-               image = mono_defaults.corlib;
-       }
-
-       type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
-       if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
-               image = mono_defaults.corlib;
-               type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
+       if (mono_reflection_parse_type (tmp, &info)) {
+               type = _mono_reflection_get_type_from_info (&info, image, FALSE);
        }
 
        g_free (tmp);
-       g_list_free (info.modifiers);
-       g_list_free (info.nested);
+       free_type_info (&info);
        return type;
 }
 
@@ -6258,12 +6538,7 @@ mono_reflection_get_token (MonoObject *obj)
                token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
        } else if (strcmp (klass->name, "FieldBuilder") == 0) {
                MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
-               MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
-               if (tb->generic_params) {
-                       g_assert_not_reached ();
-               } else {
-                       token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
-               }
+               token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
        } else if (strcmp (klass->name, "TypeBuilder") == 0) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
                token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
@@ -6271,20 +6546,22 @@ mono_reflection_get_token (MonoObject *obj)
                MonoReflectionType *tb = (MonoReflectionType *)obj;
                token = mono_class_from_mono_type (tb->type)->type_token;
        } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
-                       strcmp (klass->name, "MonoMethod") == 0) {
+                  strcmp (klass->name, "MonoMethod") == 0 ||
+                  strcmp (klass->name, "MonoGenericMethod") == 0 ||
+                  strcmp (klass->name, "MonoGenericCMethod") == 0) {
                MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
                if (m->method->is_inflated) {
-                       g_assert_not_reached ();
-               } else if (mono_method_signature (m->method)->generic_param_count) {
-                       g_assert_not_reached ();
-               } else if (m->method->klass->generic_class) {
-                       g_assert_not_reached ();
+                       MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
+                       return inflated->declaring->token;
                } else {
                        token = m->method->token;
                }
        } else if (strcmp (klass->name, "MonoField") == 0) {
                MonoReflectionField *f = (MonoReflectionField*)obj;
 
+               if (f->field->generic_info && f->field->generic_info->reflection_info)
+                       return mono_reflection_get_token (f->field->generic_info->reflection_info);
+
                token = mono_class_get_field_token (f->field);
        } else if (strcmp (klass->name, "MonoProperty") == 0) {
                MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
@@ -6318,6 +6595,8 @@ static void*
 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
 {
        int slen, type = t->type;
+       MonoClass *tklass = t->data.klass;
+
 handle_enum:
        switch (type) {
        case MONO_TYPE_U1:
@@ -6352,7 +6631,6 @@ handle_enum:
        case MONO_TYPE_U: /* error out instead? this should probably not happen */
        case MONO_TYPE_I:
 #endif
-       case MONO_TYPE_R8:
        case MONO_TYPE_U8:
        case MONO_TYPE_I8: {
                guint64 *val = g_malloc (sizeof (guint64));
@@ -6360,6 +6638,12 @@ handle_enum:
                *end = p + 8;
                return val;
        }
+       case MONO_TYPE_R8: {
+               double *val = g_malloc (sizeof (double));
+               readr8 (p, val);
+               *end = p + 8;
+               return val;
+       }
        case MONO_TYPE_VALUETYPE:
                if (t->data.klass->enumtype) {
                        type = t->data.klass->enum_basetype->type;
@@ -6408,6 +6692,18 @@ handle_type:
                } else if (subt == 0x0E) {
                        type = MONO_TYPE_STRING;
                        goto handle_enum;
+               } else if (subt == 0x1D) {
+                       MonoType simple_type = {{0}};
+                       int etype = *p;
+                       p ++;
+
+                       if (etype == 0x51)
+                               /* See Partition II, Appendix B3 */
+                               etype = MONO_TYPE_OBJECT;
+                       type = MONO_TYPE_SZARRAY;
+                       simple_type.type = etype;
+                       tklass = mono_class_from_mono_type (&simple_type);
+                       goto handle_enum;
                } else if (subt == 0x55) {
                        char *n;
                        MonoType *t;
@@ -6416,7 +6712,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);
@@ -6442,8 +6738,10 @@ handle_type:
                        *end = p;
                        return NULL;
                }
-               arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
-               basetype = t->data.klass->byval_arg.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:
@@ -6473,6 +6771,13 @@ handle_type:
                                }
                                break;
                        case MONO_TYPE_R8:
+                               for (i = 0; i < alen; i++) {
+                                       double val;
+                                       readr8 (p, &val);
+                                       mono_array_set (arr, double, i, val);
+                                       p += 8;
+                               }
+                               break;
                        case MONO_TYPE_U8:
                        case MONO_TYPE_I8:
                                for (i = 0; i < alen; i++) {
@@ -6485,12 +6790,12 @@ handle_type:
                        case MONO_TYPE_OBJECT:
                        case MONO_TYPE_STRING:
                                for (i = 0; i < alen; i++) {
-                                       MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
-                                       mono_array_set (arr, gpointer, i, item);
+                                       MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
+                                       mono_array_setref (arr, i, item);
                                }
                                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;
@@ -6501,6 +6806,50 @@ handle_type:
        return NULL;
 }
 
+static MonoObject*
+create_cattr_typed_arg (MonoType *t, MonoObject *val)
+{
+       static MonoClass *klass;
+       static MonoMethod *ctor;
+       MonoObject *retval;
+       void *params [2], *unboxed;
+
+       if (!klass)
+               klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
+       if (!ctor)
+               ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
+       
+       params [0] = mono_type_get_object (mono_domain_get (), t);
+       params [1] = val;
+       retval = mono_object_new (mono_domain_get (), klass);
+       unboxed = mono_object_unbox (retval);
+       mono_runtime_invoke (ctor, unboxed, params, NULL);
+
+       return retval;
+}
+
+static MonoObject*
+create_cattr_named_arg (void *minfo, MonoObject *typedarg)
+{
+       static MonoClass *klass;
+       static MonoMethod *ctor;
+       MonoObject *retval;
+       void *unboxed, *params [2];
+
+       if (!klass)
+               klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
+       if (!ctor)
+               ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
+
+       params [0] = minfo;
+       params [1] = typedarg;
+       retval = mono_object_new (mono_domain_get (), klass);
+       unboxed = mono_object_unbox (retval);
+       mono_runtime_invoke (ctor, unboxed, params, NULL);
+
+       return retval;
+}
+
 static gboolean
 type_is_reference (MonoType *type)
 {
@@ -6578,9 +6927,9 @@ find_event_index (MonoClass *klass, MonoEvent *event) {
 }
 
 static MonoObject*
-create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
+create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
 {
-       const char *p = data;
+       const char *p = (const char*)data;
        const char *named;
        guint32 i, j, num_named;
        MonoObject *attr;
@@ -6616,14 +6965,12 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guin
        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);
@@ -6632,10 +6979,7 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guin
                        type_name [type_len] = 0;
                        named += type_len;
                        /* FIXME: lookup the type and check type consistency */
-               } 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++;
+                       g_free (type_name);
                }
                name_len = mono_metadata_decode_blob_size (named, &named);
                name = g_malloc (name_len + 1);
@@ -6668,23 +7012,182 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guin
        return attr;
 }
 
+static MonoObject*
+create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
+{
+       MonoArray *typedargs, *namedargs;
+       MonoClass *attrklass;
+       static MonoMethod *ctor;
+       MonoDomain *domain;
+       MonoObject *attr;
+       const char *p = (const char*)data;
+       const char *named;
+       guint32 i, j, num_named;
+       void *params [3];
+
+       mono_class_init (method->klass);
+
+       if (!ctor)
+               ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
+
+       domain = mono_domain_get ();
+       if (len == 0) {
+               /* This is for Attributes with no parameters */
+               attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
+               params [0] = mono_method_get_object (domain, method, NULL);
+               params [1] = params [2] = NULL;
+               mono_runtime_invoke (method, attr, params, NULL);
+               return attr;
+       }
+
+       if (len < 2 || read16 (p) != 0x0001) /* Prolog */
+               return NULL;
+
+       typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
+       
+       /* skip prolog */
+       p += 2;
+       for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
+               MonoObject *obj, *typedarg;
+               void *val;
+
+               val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
+               obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
+                       val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
+               typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
+               mono_array_setref (typedargs, i, typedarg);
+
+               if (!type_is_reference (mono_method_signature (method)->params [i]))
+                       g_free (val);
+       }
+
+       named = p;
+       num_named = read16 (named);
+       namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
+       named += 2;
+       attrklass = method->klass;
+       for (j = 0; j < num_named; j++) {
+               gint name_len;
+               char *name, named_type, data_type;
+               named_type = *named++;
+               data_type = *named++; /* type of data */
+               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);
+                       type_name = g_malloc (type_len + 1);
+                       memcpy (type_name, named, type_len);
+                       type_name [type_len] = 0;
+                       named += type_len;
+                       /* FIXME: lookup the type and check type consistency */
+                       g_free (type_name);
+               }
+               name_len = mono_metadata_decode_blob_size (named, &named);
+               name = g_malloc (name_len + 1);
+               memcpy (name, named, name_len);
+               name [name_len] = 0;
+               named += name_len;
+               if (named_type == 0x53) {
+                       MonoObject *obj, *typedarg, *namedarg;
+                       MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
+                       void *minfo, *val = load_cattr_value (image, field->type, named, &named);
+                       
+                       minfo = mono_field_get_object (domain, NULL, field);
+                       obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
+                       typedarg = create_cattr_typed_arg (field->type, obj);
+                       namedarg = create_cattr_named_arg (minfo, typedarg);
+                       mono_array_setref (namedargs, j, namedarg);
+                       if (!type_is_reference (field->type))
+                               g_free (val);
+               } else if (named_type == 0x54) {
+                       MonoObject *obj, *typedarg, *namedarg;
+                       MonoType *prop_type;
+                       void *val, *minfo;
+                       MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
+
+                       prop_type = prop->get? mono_method_signature (prop->get)->ret :
+                            mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
+                       minfo =  mono_property_get_object (domain, NULL, prop);
+                       val = load_cattr_value (image, prop_type, named, &named);
+                       obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
+                       typedarg = create_cattr_typed_arg (prop_type, obj);
+                       namedarg = create_cattr_named_arg (minfo, typedarg);
+                       mono_array_setref (namedargs, j, namedarg);
+                       if (!type_is_reference (prop_type))
+                               g_free (val);
+               }
+               g_free (name);
+       }
+       attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
+       params [0] = mono_method_get_object (domain, method, NULL);
+       params [1] = typedargs;
+       params [2] = namedargs;
+       mono_runtime_invoke (ctor, attr, params, NULL);
+       return attr;
+}
+
 MonoArray*
 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
 {
        MonoArray *result;
-       MonoClass *klass;
        MonoObject *attr;
        int i;
 
-       klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
-       result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
+       result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
        for (i = 0; i < cinfo->num_attrs; ++i) {
                attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
-               mono_array_set (result, gpointer, i, attr);
+               mono_array_setref (result, i, attr);
+       }
+       return result;
+}
+
+static MonoArray*
+mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
+{
+       MonoArray *result;
+       MonoObject *attr;
+       int i, n;
+
+       n = 0;
+       for (i = 0; i < cinfo->num_attrs; ++i) {
+               if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
+                       n ++;
+       }
+
+       result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
+       n = 0;
+       for (i = 0; i < cinfo->num_attrs; ++i) {
+               if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
+                       attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
+                       mono_array_setref (result, n, attr);
+                       n ++;
+               }
+       }
+       return result;
+}
+
+static MonoArray*
+mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
+{
+       MonoArray *result;
+       MonoObject *attr;
+       int i;
+       
+       result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
+       for (i = 0; i < cinfo->num_attrs; ++i) {
+               attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
+               mono_array_setref (result, i, attr);
        }
        return result;
 }
 
+/**
+ * mono_custom_attrs_from_index:
+ *
+ * Returns: NULL if no attributes are found or if a loading error occurs.
+ */
 MonoCustomAttrInfo*
 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
 {
@@ -6728,11 +7231,15 @@ mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
                        break;
                }
                ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
-               if (!ainfo->attrs [i].ctor)
-                       g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
+               if (!ainfo->attrs [i].ctor) {
+                       g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
+                       g_list_free (list);
+                       g_free (ainfo);
+                       return NULL;
+               }
                data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
                ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
-               ainfo->attrs [i].data = data;
+               ainfo->attrs [i].data = (guchar*)data;
        }
        g_list_free (list);
 
@@ -6745,7 +7252,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;
@@ -6759,7 +7266,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;
@@ -6773,7 +7280,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;
@@ -6787,7 +7294,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;
@@ -6801,7 +7308,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;
@@ -6815,7 +7322,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;
@@ -6829,7 +7336,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;
@@ -6847,21 +7354,25 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
        MonoReflectionMethodAux *aux;
 
        if (method->klass->image->dynamic) {
+               MonoCustomAttrInfo *res, *ainfo;
+               int size;
+
                aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
                if (!aux || !aux->param_cattr)
                        return NULL;
-               return aux->param_cattr [param];
+
+               /* Need to copy since it will be freed later */
+               ainfo = aux->param_cattr [param];
+               size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
+               res = g_malloc0 (size);
+               memcpy (res, ainfo, size);
+               return res;
        }
 
        image = method->klass->image;
        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];
@@ -6961,8 +7472,8 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj)
                MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
                cinfo = mono_custom_attrs_from_method (rmethod->method);
        } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
-               MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
-               cinfo = mono_custom_attrs_from_method (method);
+               MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
+               cinfo = mono_custom_attrs_from_method (rmethod->method);
        } else if (strcmp ("ParameterInfo", klass->name) == 0) {
                MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
                MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
@@ -6976,6 +7487,15 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj)
        } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
                MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
                cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
+       } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
+               MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
+               cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
+       } else if (strcmp ("MethodBuilder", klass->name) == 0) {
+               MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
+               cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
+       } else if (strcmp ("FieldBuilder", klass->name) == 0) {
+               MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
+               cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
        } else { /* handle other types here... */
                g_error ("get custom attrs not yet supported for %s", klass->name);
        }
@@ -6984,64 +7504,142 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj)
 }
 
 /*
- * mono_reflection_get_custom_attrs:
+ * mono_reflection_get_custom_attrs_by_type:
  * @obj: a reflection object handle
  *
  * Return an array with all the custom attributes defined of the
- * reflection handle @obj. The objects are fully build.
+ * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
+ * of that type are returned. The objects are fully build. Return NULL if a loading error
+ * occurs.
  */
 MonoArray*
-mono_reflection_get_custom_attrs (MonoObject *obj)
+mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
 {
        MonoArray *result;
        MonoCustomAttrInfo *cinfo;
 
        cinfo = mono_reflection_get_custom_attrs_info (obj);
        if (cinfo) {
-               result = mono_custom_attrs_construct (cinfo);
+               if (attr_klass)
+                       result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
+               else
+                       result = mono_custom_attrs_construct (cinfo);
                if (!cinfo->cached)
                        mono_custom_attrs_free (cinfo);
        } else {
-               MonoClass *klass;
-               klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
-               result = mono_array_new (mono_domain_get (), klass, 0);
+               if (mono_loader_get_last_error ())
+                       return NULL;
+               result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
        }
 
        return result;
 }
 
+/*
+ * mono_reflection_get_custom_attrs:
+ * @obj: a reflection object handle
+ *
+ * Return an array with all the custom attributes defined of the
+ * reflection handle @obj. The objects are fully build. Return NULL if a loading error
+ * occurs.
+ */
+MonoArray*
+mono_reflection_get_custom_attrs (MonoObject *obj)
+{
+       return mono_reflection_get_custom_attrs_by_type (obj, NULL);
+}
+
+/*
+ * mono_reflection_get_custom_attrs_data:
+ * @obj: a reflection obj handle
+ *
+ * Returns an array of System.Reflection.CustomAttributeData,
+ * which include information about attributes reflected on
+ * types loaded using the Reflection Only methods
+ */
+MonoArray*
+mono_reflection_get_custom_attrs_data (MonoObject *obj)
+{
+       MonoArray *result;
+       MonoCustomAttrInfo *cinfo;
+
+       cinfo = mono_reflection_get_custom_attrs_info (obj);
+       if (cinfo) {
+               result = mono_custom_attrs_data_construct (cinfo);
+               if (!cinfo->cached)
+                       mono_custom_attrs_free (cinfo);
+       } else
+               result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
+
+       return result;
+}
+
+static MonoReflectionType*
+mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
+{
+        MonoMethod *method_get_underlying_system_type;
+
+        method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
+                                                                            mono_class_get_method_from_name (mono_object_class (t),
+                                                                                                             "get_UnderlyingSystemType",
+                                                                                                             0));
+        return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
+}
+
+static MonoType*
+mono_reflection_type_get_handle (MonoReflectionType* t)
+{
+        if (t->type)
+            return t->type;
+
+        t = mono_reflection_type_get_underlying_system_type (t);
+        if (t)
+            return t->type;
+
+        return NULL;
+}
+
+/**
+ * LOCKING: Assumes the loader lock is held.
+ */
 static MonoMethodSignature*
-parameters_to_signature (MonoArray *parameters) {
+parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
        MonoMethodSignature *sig;
        int count, i;
 
        count = parameters? mono_array_length (parameters): 0;
 
-       sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
+       sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
        sig->param_count = count;
        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;
 }
 
+/**
+ * LOCKING: Assumes the loader lock is held.
+ */
 static MonoMethodSignature*
-ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
+ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
        MonoMethodSignature *sig;
 
-       sig = parameters_to_signature (ctor->parameters);
+       sig = parameters_to_signature (mp, ctor->parameters);
        sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
        sig->ret = &mono_defaults.void_class->byval_arg;
        return sig;
 }
 
+/**
+ * LOCKING: Assumes the loader lock is held.
+ */
 static MonoMethodSignature*
-method_builder_to_signature (MonoReflectionMethodBuilder *method) {
+method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
        MonoMethodSignature *sig;
 
-       sig = parameters_to_signature (method->parameters);
+       sig = parameters_to_signature (mp, method->parameters);
        sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
        sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
        sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
@@ -7052,7 +7650,7 @@ static MonoMethodSignature*
 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
        MonoMethodSignature *sig;
 
-       sig = parameters_to_signature (method->parameters);
+       sig = parameters_to_signature (NULL, method->parameters);
        sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
        sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
        sig->generic_param_count = 0;
@@ -7138,9 +7736,23 @@ handle_enum:
                swap_with_size (p, argval, 4, 1);
                p += 4;
                break;
+       case MONO_TYPE_R8:
+#if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
+               p [0] = argval [4];
+               p [1] = argval [5];
+               p [2] = argval [6];
+               p [3] = argval [7];
+               p [4] = argval [0];
+               p [5] = argval [1];
+               p [6] = argval [2];
+               p [7] = argval [3];
+#else
+               swap_with_size (p, argval, 8, 1);
+#endif
+               p += 8;
+               break;
        case MONO_TYPE_U8:
        case MONO_TYPE_I8:
-       case MONO_TYPE_R8:
                swap_with_size (p, argval, 8, 1);
                p += 8;
                break;
@@ -7185,8 +7797,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);
@@ -7221,7 +7843,19 @@ handle_type:
                *retbuffer = buffer;
                eclass = type->data.klass;
                arg_eclass = mono_object_class (arg)->element_class;
-               if (eclass->valuetype && arg_eclass->valuetype) {
+
+               if (!eclass) {
+                       /* Happens when we are called from the MONO_TYPE_OBJECT case below */
+                       eclass = mono_defaults.object_class;
+               }
+               if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
+                       char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
+                       int elsize = mono_class_array_element_size (arg_eclass);
+                       for (i = 0; i < len; ++i) {
+                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
+                               elptr += elsize;
+                       }
+               } else if (eclass->valuetype && arg_eclass->valuetype) {
                        char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
                        int elsize = mono_class_array_element_size (eclass);
                        for (i = 0; i < len; ++i) {
@@ -7235,12 +7869,17 @@ handle_type:
                }
                break;
        }
-       /* it may be a boxed value or a Type */
        case MONO_TYPE_OBJECT: {
                MonoClass *klass;
                char *str;
                guint32 slen;
 
+               /*
+                * The parameter type is 'object' but the type of the actual
+                * argument is not. So we have to add type information to the blob
+                * too. This is completely undocumented in the spec.
+                */
+
                if (arg == NULL) {
                        *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
                        *p++ = 0xFF;
@@ -7249,7 +7888,7 @@ handle_type:
                
                klass = mono_object_class (arg);
 
-               if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
+               if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
                        *p++ = 0x50;
                        goto handle_type;
                } else if (klass->enumtype) {
@@ -7258,6 +7897,15 @@ handle_type:
                        simple_type = MONO_TYPE_STRING;
                        *p++ = 0x0E;
                        goto handle_enum;
+               } else if (klass->rank == 1) {
+                       *p++ = 0x1D;
+                       if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
+                               /* See Partition II, Appendix B3 */
+                               *p++ = 0x51;
+                       else
+                               *p++ = klass->element_class->byval_arg.type;
+                       encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
+                       break;
                } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
                        *p++ = simple_type = klass->byval_arg.type;
                        goto handle_enum;
@@ -7289,28 +7937,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);
@@ -7332,8 +7960,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);
@@ -7368,10 +8030,12 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
        MONO_ARCH_SAVE_REGS;
 
        if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
-               sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
+               /* sig is freed later so allocate it in the heap */
+               sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
        } else {
                sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
        }
+
        g_assert (mono_array_length (ctorArgs) == sig->param_count);
        buflen = 256;
        p = buffer = g_malloc (buflen);
@@ -7428,6 +8092,19 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
        return result;
 }
 
+#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
+
 /*
  * mono_reflection_setup_internal_class:
  * @tb: a TypeBuilder object
@@ -7462,26 +8139,27 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
                klass = mono_class_from_mono_type (tb->type.type);
                klass->parent = NULL;
                /* fool mono_class_setup_parent */
-               g_free (klass->supertypes);
                klass->supertypes = NULL;
                mono_class_setup_parent (klass, parent);
                mono_class_setup_mono_type (klass);
                mono_loader_unlock ();
                return;
        }
-       
-       klass = g_new0 (MonoClass, 1);
+
+       klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
 
        klass->image = &tb->module->dynamic_image->image;
 
        klass->inited = 1; /* we lie to the runtime */
-       klass->name = mono_string_to_utf8 (tb->name);
-       klass->name_space = mono_string_to_utf8 (tb->nspace);
+       klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
+       klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
        klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
        klass->flags = tb->attrs;
 
        klass->element_class = klass;
-       klass->reflection_info = tb; /* need to pin. */
+
+       MOVING_GC_REGISTER (&klass->reflection_info);
+       klass->reflection_info = tb;
 
        /* Put into cache so mono_class_get () will find it */
        mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
@@ -7545,9 +8223,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;
 }
 
 /*
@@ -7571,7 +8247,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;
 
@@ -7584,7 +8260,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);
 }
 
 /*
@@ -7612,6 +8288,11 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
 
                fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
 
+               if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
+                       mono_loader_unlock ();
+                       return;
+               }
+
                klass->enum_basetype = fb->type->type;
                klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
                if (!klass->element_class)
@@ -7710,12 +8391,12 @@ mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
                if (spec->data.custom_data.custom_name) {
                        mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
                        if (mtype)
-                               minfo->marshaltyperef = mono_type_get_object (domain, mtype);
+                               MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
 
-                       minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
+                       MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
                }
                if (spec->data.custom_data.cookie)
-                       minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
+                       MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
                break;
 
        default:
@@ -7734,24 +8415,40 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
        MonoMethodNormal *pm;
        MonoMarshalSpec **specs;
        MonoReflectionMethodAux *method_aux;
+       MonoMemPool *mp;
+       gboolean dynamic;
        int i;
 
+       g_assert (!klass->generic_class);
+
+       /*
+        * Methods created using a MethodBuilder should have their memory allocated
+        * inside the image mempool, while dynamic methods should have their memory
+        * malloc'd.
+        */
+       dynamic = rmb->refs != NULL;
+       mp = dynamic ? NULL : klass->image->mempool;
+
+       mono_loader_lock ();
+
        if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
                        (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
-               m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
+               m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
        else if (rmb->refs)
-               m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
+               m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
        else
-               m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
+               m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
 
        pm = (MonoMethodNormal*)m;
 
+       m->dynamic = dynamic;
        m->slot = -1;
        m->flags = rmb->attrs;
        m->iflags = rmb->iattrs;
-       m->name = mono_string_to_utf8 (rmb->name);
+       m->name = mp_string_to_utf8 (mp, rmb->name);
        m->klass = klass;
        m->signature = sig;
+       m->skip_visibility = rmb->skip_visibility;
        if (rmb->table_idx)
                m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
 
@@ -7765,17 +8462,18 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
 
                method_aux = g_new0 (MonoReflectionMethodAux, 1);
 
-               method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
-               method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
+               method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
+               method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
                
-               ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
+               ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
 
                if (klass->image->dynamic)
                        g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
 
+               mono_loader_unlock ();
+
                return m;
-       } else if (!m->klass->dummy && 
-                          !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
+       } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
                           !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
                MonoMethodHeader *header;
                guint32 code_size;
@@ -7805,10 +8503,10 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                        }
                }
 
-               header = g_malloc0 (sizeof (MonoMethodHeader) + 
+               header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) + 
                        (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
                header->code_size = code_size;
-               header->code = g_malloc (code_size);
+               header->code = mp_g_malloc (mp, code_size);
                memcpy ((char*)header->code, code, code_size);
                header->max_stack = max_stack;
                header->init_locals = rmb->init_locals;
@@ -7818,7 +8516,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                        MonoReflectionLocalBuilder *lb = 
                                mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
 
-                       header->locals [i] = g_new0 (MonoType, 1);
+                       header->locals [i] = mp_g_new0 (mp, MonoType, 1);
                        memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
                }
 
@@ -7835,9 +8533,10 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                int count = mono_array_length (rmb->generic_params);
                MonoGenericContainer *container;
 
-               pm->generic_container = container = rmb->generic_container;
+               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 =
@@ -7845,6 +8544,12 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
 
                        container->type_params [i] = *gp->type.type->data.generic_param;
                }
+
+               if (klass->generic_container) {
+                       container->parent = klass->generic_container;
+                       container->context.class_inst = klass->generic_container->context.class_inst;
+               }
+               container->context.method_inst = mono_get_shared_generic_inst (container);
        }
 
        if (rmb->refs) {
@@ -7854,7 +8559,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
 
                m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
 
-               mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
+               mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
                data [0] = GUINT_TO_POINTER (rmb->nrefs);
                for (i = 0; i < rmb->nrefs; ++i)
                        data [i + 1] = rmb->refs [i];
@@ -7865,26 +8570,27 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
        /* Parameter info */
        if (rmb->pinfo) {
                if (!method_aux)
-                       method_aux = g_new0 (MonoReflectionMethodAux, 1);
-               method_aux->param_names = g_new0 (char *, mono_method_signature (m)->param_count + 1);
+                       method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
+               method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
                for (i = 0; i <= m->signature->param_count; ++i) {
                        MonoReflectionParamBuilder *pb;
                        if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
                                if ((i > 0) && (pb->attrs)) {
                                        /* Make a copy since it might point to a shared type structure */
-                                       m->signature->params [i - 1] = g_memdup (m->signature->params [i - 1], sizeof (MonoType) + ((m->signature->params [i - 1]->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)));
+                                       /* FIXME: Alloc this from a mempool */
+                                       m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]);
                                        m->signature->params [i - 1]->attrs = pb->attrs;
                                }
 
-                               if (pb->def_value) {
+                               if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
                                        MonoDynamicImage *assembly;
                                        guint32 idx, def_type, len;
                                        char *p;
                                        const char *p2;
 
                                        if (!method_aux->param_defaults) {
-                                               method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
-                                               method_aux->param_default_types = g_new0 (guint32, m->signature->param_count + 1);
+                                               method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
+                                               method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
                                        }
                                        assembly = (MonoDynamicImage*)klass->image;
                                        idx = encode_constant (assembly, pb->def_value, &def_type);
@@ -7892,16 +8598,16 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                                        p = assembly->blob.data + idx;
                                        len = mono_metadata_decode_blob_size (p, &p2);
                                        len += p2 - p;
-                                       method_aux->param_defaults [i] = g_malloc (len);
+                                       method_aux->param_defaults [i] = mp_g_malloc (mp, len);
                                        method_aux->param_default_types [i] = def_type;
                                        memcpy ((gpointer)method_aux->param_defaults [i], p, len);
                                }
 
                                if (pb->name)
-                                       method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
+                                       method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
                                if (pb->cattrs) {
                                        if (!method_aux->param_cattr)
-                                               method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
+                                               method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
                                        method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
                                }
                        }
@@ -7916,7 +8622,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                        if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
                                if (pb->marshal_info) {
                                        if (specs == NULL)
-                                               specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
+                                               specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
                                        specs [pb->position] = 
                                                mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
                                }
@@ -7924,13 +8630,15 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                }
        if (specs != NULL) {
                if (!method_aux)
-                       method_aux = g_new0 (MonoReflectionMethodAux, 1);
+                       method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
                method_aux->param_marshall = specs;
        }
 
        if (klass->image->dynamic && method_aux)
                g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
 
+       mono_loader_unlock ();
+
        return m;
 }      
 
@@ -7940,7 +8648,9 @@ ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
        ReflectionMethodBuilder rmb;
        MonoMethodSignature *sig;
 
-       sig = ctor_builder_to_signature (mb);
+       mono_loader_lock ();
+       sig = ctor_builder_to_signature (klass->image->mempool, mb);
+       mono_loader_unlock ();
 
        reflection_methodbuilder_from_ctor_builder (&rmb, mb);
 
@@ -7961,7 +8671,9 @@ methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
        ReflectionMethodBuilder rmb;
        MonoMethodSignature *sig;
 
-       sig = method_builder_to_signature (mb);
+       mono_loader_lock ();
+       sig = method_builder_to_signature (klass->image->mempool, mb);
+       mono_loader_unlock ();
 
        reflection_methodbuilder_from_method_builder (&rmb, mb);
 
@@ -7982,9 +8694,6 @@ fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder*
        const char *p, *p2;
        guint32 len, idx;
 
-       if (fb->handle)
-               return fb->handle;
-
        field = g_new0 (MonoClassField, 1);
 
        field->name = mono_string_to_utf8 (fb->name);
@@ -7996,11 +8705,10 @@ fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder*
                field->type = fb->type->type;
        }
        if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
-               field->data = mono_array_addr (fb->rva_data, char, 0);
+               field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
        if (fb->offset != -1)
                field->offset = fb->offset;
        field->parent = klass;
-       fb->handle = field;
        mono_save_custom_attrs (klass->image, field, fb->cattrs);
 
        if (fb->def_value) {
@@ -8018,23 +8726,14 @@ fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder*
        return field;
 }
 
-static MonoType*
-do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
-                                           MonoType *parent)
+MonoType*
+mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
 {
        MonoClass *klass;
        MonoReflectionTypeBuilder *tb = NULL;
-       MonoGenericClass *gclass, *cached;
-       MonoDynamicGenericClass *dgclass = NULL;
        gboolean is_dynamic = FALSE;
        MonoDomain *domain;
-       MonoType *geninst;
-       int icount, 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;
+       MonoClass *geninst;
 
        mono_loader_lock ();
 
@@ -8043,7 +8742,6 @@ do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_a
        if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
                tb = (MonoReflectionTypeBuilder *) type;
 
-               icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
                is_dynamic = TRUE;
        } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
                MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
@@ -8052,176 +8750,56 @@ do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_a
                g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
                tb = (MonoReflectionTypeBuilder *) rgt;
 
-               icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
                is_dynamic = TRUE;
-       } else {
-               icount = klass->interface_count;
-       }
-
-       if (is_dynamic) {
-               dgclass = g_new0 (MonoDynamicGenericClass, 1);
-               gclass = &dgclass->generic_class;
-               gclass->is_dynamic = TRUE;
-       } else
-               gclass = g_new0 (MonoGenericClass, 1);
-
-       gclass->inst = g_new0 (MonoGenericInst, 1);
-
-       gclass->inst->type_argc = type_argc;
-       gclass->inst->type_argv = types;
-       gclass->inst->is_reference = 1;
-
-       for (i = 0; i < gclass->inst->type_argc; ++i) {
-               if (!gclass->inst->is_open)
-                       gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
-               if (gclass->inst->is_reference)
-                       gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
-       }
-
-       gclass->container_class = klass;
-
-       if (klass->generic_class) {
-               MonoGenericClass *kgclass = klass->generic_class;
-               MonoGenericClass *ogclass = gclass;
-
-               ogclass->context = g_new0 (MonoGenericContext, 1);
-               ogclass->context->container = ogclass->container_class->generic_container;
-               ogclass->context->gclass = ogclass;
-
-               if (is_dynamic) {
-                       dgclass = g_new0 (MonoDynamicGenericClass, 1);
-                       gclass = &dgclass->generic_class;
-                       gclass->is_dynamic = TRUE;
-               } else
-                       gclass = g_new0 (MonoGenericClass, 1);
-
-               gclass->inst = g_new0 (MonoGenericInst, 1);
-
-               gclass->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->container_class = kgclass->container_class;
        }
 
-       geninst = g_new0 (MonoType, 1);
-       geninst->type = MONO_TYPE_GENERICINST;
+       /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
+       if (tb && tb->generic_container)
+               mono_reflection_create_generic_class (tb);
 
-       cached = mono_metadata_lookup_generic_class (gclass);
-       if (cached) {
-               g_free (gclass);
+       klass = mono_class_from_mono_type (type->type);
+       if (!klass->generic_container) {
                mono_loader_unlock ();
-               geninst->data.generic_class = cached;
-               return geninst;
+               return NULL;
        }
 
-       geninst->data.generic_class = gclass;
-
-       gclass->parent = parent;
-
-       gclass->context = g_new0 (MonoGenericContext, 1);
-       gclass->context->container = gclass->container_class->generic_container;
-       gclass->context->gclass = gclass;
-
-       gclass->ifaces = g_new0 (MonoType *, icount);
-       gclass->count_ifaces = icount;
-
-       for (i = 0; i < icount; i++) {
-               MonoReflectionType *itype;
+       if (klass->wastypebuilder) {
+               tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
 
-               if (tb)
-                       itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
-               else
-                       itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
-               gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
-               if (!gclass->ifaces [i])
-                       gclass->ifaces [i] = itype->type;
+               is_dynamic = TRUE;
        }
 
-       mono_class_create_generic (gclass);
-
        mono_loader_unlock ();
 
-       return geninst;
+       geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
+
+       return &geninst->byval_arg;
 }
 
-MonoType*
-mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
+MonoClass*
+mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
 {
-       MonoClass *klass, *pklass = NULL;
-       MonoReflectionType *parent = NULL;
-       MonoType *the_parent = NULL, *geninst;
-       MonoReflectionTypeBuilder *tb = NULL;
        MonoGenericClass *gclass;
-       MonoDomain *domain;
+       MonoGenericInst *inst;
 
-       domain = mono_object_domain (type);
-       klass = mono_class_from_mono_type (type->type);
-
-       if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
-               tb = (MonoReflectionTypeBuilder *) type;
-
-               if (tb->parent) {
-                       parent = tb->parent;
-                       pklass = mono_class_from_mono_type (parent->type);
-               }
-       } else {
-               pklass = klass->parent;
-               if (pklass)
-                       parent = mono_type_get_object (domain, &pklass->byval_arg);
-               else if (klass->generic_class && klass->generic_class->parent) {
-                       parent = mono_type_get_object (domain, klass->generic_class->parent);
-                       pklass = mono_class_from_mono_type (klass->generic_class->parent);
-               }
-       }
-
-       if (pklass && pklass->generic_class)
-               the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
-
-       geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
-       if (!geninst)
-               return NULL;
-
-       gclass = geninst->data.generic_class;
+       g_assert (klass->generic_container);
 
-       return geninst;
-}
+       inst = mono_metadata_get_generic_inst (type_argc, types);
+       gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
 
-static inline MonoType*
-dup_type (const MonoType *original)
-{
-       MonoType *r = g_new0 (MonoType, 1);
-       *r = *original;
-       r->attrs = original->attrs;
-       r->byref = original->byref;
-       if (original->type == MONO_TYPE_PTR)
-               r->data.type = dup_type (original->data.type);
-       mono_stats.generics_metadata_size += sizeof (MonoType);
-       return r;
+       return mono_generic_class_get_class (gclass);
 }
 
 MonoReflectionMethod*
 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
 {
+       MonoClass *klass;
        MonoMethod *method, *inflated;
+       MonoMethodInflated *imethod;
        MonoReflectionMethodBuilder *mb = NULL;
-       MonoGenericContainer *container;
-       MonoGenericMethod *gmethod;
-       MonoGenericContext *context;
+       MonoGenericContext tmp_context;
        MonoGenericInst *ginst;
+       MonoType **type_argv;
        int count, i;
 
        MONO_ARCH_SAVE_REGS;
@@ -8238,53 +8816,31 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
                method = rmethod->method;
        }
 
+       klass = method->klass;
+
+       if (method->is_inflated)
+               method = ((MonoMethodInflated *) method)->declaring;
+
        count = mono_method_signature (method)->generic_param_count;
        if (count != mono_array_length (types))
                return NULL;
 
-       container = ((MonoMethodNormal*) method)->generic_container;
-       g_assert (container);
-
-       if (!container->method_hash)
-               container->method_hash = g_hash_table_new (
-                       (GHashFunc) mono_metadata_generic_method_hash,
-                       (GCompareFunc) mono_metadata_generic_method_equal);
-
-       ginst = g_new0 (MonoGenericInst,1 );
-       ginst->type_argc = count;
-       ginst->type_argv = g_new0 (MonoType *, count);
-       ginst->is_reference = 1;
+       type_argv = g_new0 (MonoType *, count);
        for (i = 0; i < count; i++) {
                MonoReflectionType *garg = mono_array_get (types, gpointer, i);
-               ginst->type_argv [i] = dup_type (garg->type);
-
-               if (!ginst->is_open)
-                       ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
-               if (ginst->is_reference)
-                       ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
+               type_argv [i] = garg->type;
        }
-       ginst = mono_metadata_lookup_generic_inst (ginst);
+       ginst = mono_metadata_get_generic_inst (count, type_argv);
+       g_free (type_argv);
 
-       gmethod = g_new0 (MonoGenericMethod, 1);
-       gmethod->container = container;
-       gmethod->inst = ginst;
+       tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
+       tmp_context.method_inst = ginst;
 
-       inflated = g_hash_table_lookup (container->method_hash, gmethod);
-       if (inflated) {
-               g_free (gmethod);
+       inflated = mono_class_inflate_generic_method (method, &tmp_context);
+       imethod = (MonoMethodInflated *) inflated;
 
-               return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
-       }
-
-       gmethod->reflection_info = rmethod;
-
-       context = g_new0 (MonoGenericContext, 1);
-       context->container = container;
-       context->gclass = method->klass->generic_class;
-       context->gmethod = gmethod;
-
-       inflated = mono_class_inflate_generic_method (method, context, NULL);
-       g_hash_table_insert (container->method_hash, gmethod, inflated);
+       MOVING_GC_REGISTER (&imethod->reflection_info);
+       imethod->reflection_info = rmethod;
 
        return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
 }
@@ -8292,48 +8848,43 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
 static MonoMethod *
 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
 {
-       MonoGenericMethod *gmethod;
-       MonoGenericClass *gclass;
+       MonoMethodInflated *imethod;
+       MonoGenericContext tmp_context;
        MonoGenericContext *context;
-       int i;
-
-       gclass = type->type.type->data.generic_class;
-
-       gmethod = g_new0 (MonoGenericMethod, 1);
-       gmethod->inst = g_new0 (MonoGenericInst, 1);
-       gmethod->reflection_info = obj;
+       MonoClass *klass;
 
-       gmethod->inst->type_argc = mono_method_signature (method)->generic_param_count;
-       gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
+       klass = mono_class_from_mono_type (type->type.type);
+       g_assert (klass->generic_class);
+       context = mono_class_get_context (klass);
 
-       for (i = 0; i < gmethod->inst->type_argc; i++) {
-               MonoMethodNormal *mn = (MonoMethodNormal *) method;
-               MonoGenericParam *gparam = &mn->generic_container->type_params [i];
+       if (method->generic_container) {
+               g_assert (method->klass == klass->generic_class->container_class);
 
-               g_assert (gparam->pklass);
-               gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
+               tmp_context.class_inst = klass->generic_class->context.class_inst;
+               tmp_context.method_inst = method->generic_container->context.method_inst;
+               context = &tmp_context;
        }
 
-       context = g_new0 (MonoGenericContext, 1);
-       context->container = gclass->container_class->generic_container;
-       context->gclass = gclass;
-       context->gmethod = gmethod;
-
-       return mono_class_inflate_generic_method (method, context, gclass->klass);
+       imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
+       if (method->generic_container) {
+               MOVING_GC_REGISTER (&imethod->reflection_info);
+               imethod->reflection_info = obj;
+       }
+       return (MonoMethod *) imethod;
 }
 
 static MonoMethod *
 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
 {
        MonoMethod *method;
-       MonoClass *klass;
+       MonoClass *gklass;
 
-       klass = mono_class_from_mono_type (type->type.type);
+       gklass = mono_class_from_mono_type (type->generic_type->type);
 
        if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
-               method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
+               method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
        else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
-               method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
+               method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
        else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
                method = ((MonoReflectionMethod *) obj)->method;
        else {
@@ -8351,7 +8902,7 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
 {
        MonoGenericClass *gclass;
        MonoDynamicGenericClass *dgclass;
-       MonoClass *klass, *gklass, *pklass;
+       MonoClass *klass, *gklass;
        int i;
 
        MONO_ARCH_SAVE_REGS;
@@ -8368,13 +8919,6 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
        gklass = gclass->container_class;
        mono_class_init (gklass);
 
-       if (gclass->parent)
-               pklass = mono_class_from_mono_type (gclass->parent);
-       else
-               pklass = gklass->parent;
-
-       mono_class_setup_parent (klass, pklass);
-
        dgclass->count_methods = methods ? mono_array_length (methods) : 0;
        dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
        dgclass->count_fields = fields ? mono_array_length (fields) : 0;
@@ -8415,11 +8959,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, gclass->context);
+               dgclass->fields [i].type = mono_class_inflate_generic_type (
+                       field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
        }
 
        for (i = 0; i < dgclass->count_properties; i++) {
@@ -8479,8 +9026,7 @@ static void
 ensure_runtime_vtable (MonoClass *klass)
 {
        MonoReflectionTypeBuilder *tb = klass->reflection_info;
-       int i, num, j, onum;
-       MonoMethod **overrides;
+       int i, num, j;
 
        if (!tb || klass->wastypebuilder)
                return;
@@ -8490,7 +9036,7 @@ ensure_runtime_vtable (MonoClass *klass)
        num = tb->ctors? mono_array_length (tb->ctors): 0;
        num += tb->num_methods;
        klass->method.count = num;
-       klass->methods = g_new (MonoMethod*, num);
+       klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
        num = tb->ctors? mono_array_length (tb->ctors): 0;
        for (i = 0; i < num; ++i)
                klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
@@ -8501,22 +9047,50 @@ ensure_runtime_vtable (MonoClass *klass)
 
        if (tb->interfaces) {
                klass->interface_count = mono_array_length (tb->interfaces);
-               klass->interfaces = g_new (MonoClass*, klass->interface_count);
+               klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
                for (i = 0; i < klass->interface_count; ++i) {
                        MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
                        klass->interfaces [i] = mono_class_from_mono_type (iface->type);
                }
        }
 
-       if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
+       if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
                for (i = 0; i < klass->method.count; ++i)
                        klass->methods [i]->slot = i;
+               
+               mono_class_setup_interface_offsets (klass);
+       }
+
+       /*
+        * The generic vtable is needed even if image->run is not set since some
+        * runtime code like ves_icall_Type_GetMethodsByName depends on 
+        * method->slot being defined.
+        */
+
+       /* 
+        * tb->methods could not be freed since it is used for determining 
+        * overrides during dynamic vtable construction.
+        */
+}
+
+void
+mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
+{
+       MonoReflectionTypeBuilder *tb;
+       int i, onum;
+
+       *overrides = NULL;
+       *num_overrides = 0;
 
-       if (!((MonoDynamicImage*)klass->image)->run)
-               /* No need to create a generic vtable */
+       g_assert (klass->image->dynamic);
+
+       if (!klass->reflection_info)
                return;
 
-       /* Overrides */
+       g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
+
+       tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
+
        onum = 0;
        if (tb->methods) {
                for (i = 0; i < tb->num_methods; ++i) {
@@ -8527,20 +9101,21 @@ ensure_runtime_vtable (MonoClass *klass)
                }
        }
 
-       overrides = g_new0 (MonoMethod*, onum * 2);
+       if (onum) {
+               *overrides = g_new0 (MonoMethod*, onum * 2);
 
-       if (tb->methods) {
                onum = 0;
                for (i = 0; i < tb->num_methods; ++i) {
                        MonoReflectionMethodBuilder *mb = 
                                mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
                        if (mb->override_method) {
-                               /* FIXME: What if 'override_method' is a MethodBuilder ? */
-                               overrides [onum * 2] = 
+                               (*overrides) [onum * 2] = 
                                        mb->override_method->method;
-                               overrides [onum * 2 + 1] =
+                               (*overrides) [onum * 2 + 1] =
                                        mb->mhandle;
 
+                               /* FIXME: What if 'override_method' is a MethodBuilder ? */
+                               g_assert (mb->override_method->method);
                                g_assert (mb->mhandle);
 
                                onum ++;
@@ -8548,8 +9123,7 @@ ensure_runtime_vtable (MonoClass *klass)
                }
        }
 
-       mono_class_setup_vtable_general (klass, overrides, onum);
-       g_free (overrides);
+       *num_overrides = onum;
 }
 
 static void
@@ -8564,7 +9138,6 @@ typebuilder_setup_fields (MonoClass *klass)
 
        klass->field.count = tb->num_fields;
        klass->field.first = 0;
-       klass->field.last = klass->field.count;
 
        if (!klass->field.count)
                return;
@@ -8614,7 +9187,6 @@ typebuilder_setup_properties (MonoClass *klass)
 
        klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
        klass->property.first = 0;
-       klass->property.last = klass->property.count;
 
        klass->properties = g_new0 (MonoProperty, klass->property.count);
        for (i = 0; i < klass->property.count; ++i) {
@@ -8626,6 +9198,8 @@ typebuilder_setup_properties (MonoClass *klass)
                        klass->properties [i].get = pb->get_method->mhandle;
                if (pb->set_method)
                        klass->properties [i].set = pb->set_method->mhandle;
+
+               mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
        }
 }
 
@@ -8670,7 +9244,6 @@ typebuilder_setup_events (MonoClass *klass)
 
        klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
        klass->event.first = 0;
-       klass->event.last = klass->event.count;
 
        klass->events = g_new0 (MonoEvent, klass->event.count);
        for (i = 0; i < klass->event.count; ++i) {
@@ -8701,18 +9274,26 @@ MonoReflectionType*
 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
 {
        MonoClass *klass;
+       MonoDomain* domain;
        MonoReflectionType* res;
        int i;
 
        MONO_ARCH_SAVE_REGS;
 
+       domain = mono_object_domain (tb);
        klass = my_mono_class_from_mono_type (tb->type.type);
 
        mono_save_custom_attrs (klass->image, klass, tb->cattrs);
-
+       
+       /* 
+        * we need to lock the domain because the lock will be taken inside
+        * So, we need to keep the locking order correct.
+        */
+       mono_domain_lock (domain);
        mono_loader_lock ();
        if (klass->wastypebuilder) {
                mono_loader_unlock ();
+               mono_domain_unlock (domain);
                return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
        }
        /*
@@ -8723,14 +9304,17 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        klass->has_cctor = 1;
        klass->has_finalize = 1;
 
+#if 0
        if (!((MonoDynamicImage*)klass->image)->run) {
                if (klass->generic_container) {
                        /* FIXME: The code below can't handle generic classes */
                        klass->wastypebuilder = TRUE;
                        mono_loader_unlock ();
+                       mono_domain_unlock (domain);
                        return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
                }
        }
+#endif
 
        /* enums are done right away */
        if (!klass->enumtype)
@@ -8747,8 +9331,8 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        if (klass->parent) {
                if (!klass->parent->size_inited)
                        mono_class_init (klass->parent);
-               klass->instance_size += klass->parent->instance_size;
-               klass->class_size += klass->parent->class_size;
+               klass->instance_size = klass->parent->instance_size;
+               klass->sizes.class_size = 0;
                klass->min_align = klass->parent->min_align;
                /* if the type has no fields we won't call the field_setup
                 * routine which sets up klass->has_references.
@@ -8765,12 +9349,19 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        typebuilder_setup_properties (klass);
 
        typebuilder_setup_events (klass);
-
+       
        klass->wastypebuilder = TRUE;
        mono_loader_unlock ();
+       mono_domain_unlock (domain);
+
+       if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
+               mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+               mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
+       }
 
        res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
        g_assert (res != (MonoReflectionType*)tb);
+
        return res;
 }
 
@@ -8789,32 +9380,18 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam
                        gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
                param->owner = gparam->mbuilder->generic_container;
        } else if (gparam->tbuilder) {
-               MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
-               MonoGenericContainer *container = gparam->tbuilder->generic_container;
-
-               while (nesting) {
-                       int count;
-
-                       count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
-                       if (gparam->index >= count)
-                               break;
-
-                       container = nesting->generic_container;
-                       nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
-               }
-
-               g_assert (container);
-               param->owner = container;
+               g_assert (gparam->tbuilder->generic_container);
+               param->owner = gparam->tbuilder->generic_container;
        }
 
-       param->method = NULL;
        param->name = mono_string_to_utf8 (gparam->name);
        param->num = gparam->index;
 
        image = &gparam->tbuilder->module->dynamic_image->image;
        mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
 
-       param->pklass->reflection_info = gparam;
+       MOVING_GC_REGISTER (&param->pklass->reflection_info);
+       param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
 
        gparam->type.type = g_new0 (MonoType, 1);
        gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
@@ -8829,24 +9406,21 @@ mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
        guint32 na = mono_array_length (sig->arguments);
        guint32 buflen, i;
        MonoArray *result;
-       char *buf, *p;
-
-       MONO_ARCH_SAVE_REGS;
+       SigBuffer buf;
 
-       p = buf = g_malloc (10 + na * 10);
+       sigbuffer_init (&buf, 32);
 
-       mono_metadata_encode_value (0x07, p, &p);
-       mono_metadata_encode_value (na, p, &p);
+       sigbuffer_add_value (&buf, 0x07);
+       sigbuffer_add_value (&buf, na);
        for (i = 0; i < na; ++i) {
                MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
-               encode_reflection_type (assembly, type, p, &p);
+               encode_reflection_type (assembly, type, &buf);
        }
 
-       buflen = p - buf;
+       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;
 }
@@ -8858,23 +9432,20 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
        guint32 na = mono_array_length (sig->arguments);
        guint32 buflen, i;
        MonoArray *result;
-       char *buf, *p;
-
-       MONO_ARCH_SAVE_REGS;
+       SigBuffer buf;
 
-       p = buf = g_malloc (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;
+       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;
 }
@@ -8884,6 +9455,7 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
 {
        ReflectionMethodBuilder rmb;
        MonoMethodSignature *sig;
+       GSList *l;
        int i;
 
        sig = dynamic_method_to_signature (mb);
@@ -8893,29 +9465,83 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
        /*
         * Resolve references.
         */
+       /* 
+        * Every second entry in the refs array is reserved for storing handle_class,
+        * which is needed by the ldtoken implementation in the JIT.
+        */
        rmb.nrefs = mb->nrefs;
        rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
-       for (i = 0; i < mb->nrefs; ++i) {
+       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));
-                       return;
+               gpointer ref;
+               MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
+
+               if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
+                       MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
+                       /*
+                        * The referenced DynamicMethod should already be created by the managed
+                        * code, except in the case of circular references. In that case, we store
+                        * method in the refs array, and fix it up later when the referenced 
+                        * DynamicMethod is created.
+                        */
+                       if (method->mhandle) {
+                               ref = method->mhandle;
+                       } else {
+                               /* FIXME: GC object stored in unmanaged memory */
+                               ref = method;
+
+                               /* FIXME: GC object stored in unmanaged memory */
+                               method->referenced_by = g_slist_append (method->referenced_by, mb);
+                       }
+                       handle_class = mono_defaults.methodhandle_class;
+               } else {
+                       ref = resolve_object (mb->module->image, obj, &handle_class);
+                       if (!ref) {
+                               g_free (rmb.refs);
+                               mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
+                               return;
+                       }
                }
-               rmb.refs [i] = ref;
+
+               rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
+               rmb.refs [i + 1] = handle_class;
        }               
 
        /* FIXME: class */
        mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
 
+       /* Fix up refs entries pointing at us */
+       for (l = mb->referenced_by; l; l = l->next) {
+               MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
+               MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
+               gpointer *data;
+               
+               g_assert (method->mhandle);
+
+               data = (gpointer*)wrapper->method_data;
+               for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
+                       if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
+                               data [i + 1] = mb->mhandle;
+               }
+       }
+       g_slist_free (mb->referenced_by);
+
        g_free (rmb.refs);
 
        /* ilgen is no longer needed */
        mb->ilgen = NULL;
 }
 
+void
+mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
+{
+       g_assert (mb);
+
+       if (mb->mhandle)
+               mono_runtime_free_method (
+                       mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
+}
+
 /**
  * mono_reflection_lookup_dynamic_token:
  *
@@ -8949,11 +9575,10 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
                result = mono_class_from_mono_type (tb->type);
                *handle_class = mono_defaults.typehandle_class;
                g_assert (result);
-       } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
-               result = ((MonoReflectionMethod*)obj)->method;
-               *handle_class = mono_defaults.methodhandle_class;
-               g_assert (result);
-       } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
+       } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
+                  strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
+                  strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
+                  strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
                result = ((MonoReflectionMethod*)obj)->method;
                *handle_class = mono_defaults.methodhandle_class;
                g_assert (result);
@@ -9050,6 +9675,12 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
 
                result = sig;
                *handle_class = NULL;
+       } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
+               MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
+               /* Already created by the managed code */
+               g_assert (method->mhandle);
+               result = method->mhandle;
+               *handle_class = mono_defaults.methodhandle_class;
        } else {
                g_print (obj->vtable->klass->name);
                g_assert_not_reached ();
@@ -9089,12 +9720,17 @@ const static guint32 declsec_flags_map[] = {
 static guint32
 mono_declsec_get_flags (MonoImage *image, guint32 token)
 {
-       guint32 index = mono_metadata_declsec_from_index (image, token);
+       int index = mono_metadata_declsec_from_index (image, token);
        MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
        guint32 result = 0;
        guint32 action;
        int i;
 
+       /* HasSecurity can be present for other, not specially encoded, attributes,
+          e.g. SuppressUnmanagedCodeSecurityAttribute */
+       if (index < 0)
+               return 0;
+
        for (i = index; i < t->rows; i++) {
                guint32 cols [MONO_DECL_SECURITY_SIZE];
 
@@ -9267,7 +9903,7 @@ mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
                return FALSE;
 
        /* we want the original as the wrapper is "free" of the security informations */
-       if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+       if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
                method = mono_marshal_method_from_wrapper (method);
                if (!method)
                        return FALSE;
@@ -9315,7 +9951,7 @@ mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass
                return FALSE;
 
        /* we want the original as the wrapper is "free" of the security informations */
-       if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+       if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
                method = mono_marshal_method_from_wrapper (method);
                if (!method)
                        return FALSE;
@@ -9390,7 +10026,7 @@ mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActi
                return FALSE;
 
        /* we want the original as the wrapper is "free" of the security informations */
-       if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+       if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
                method = mono_marshal_method_from_wrapper (method);
                if (!method)
                        return FALSE;
@@ -9474,23 +10110,34 @@ mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDe
 }
 
 gboolean
-mono_reflection_call_is_assignable_from (MonoClass *klass, MonoClass *oklass)
+mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
 {
        MonoObject *res, *exc;
        void *params [1];
+       static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
        static MonoMethod *method = NULL;
 
+       if (!System_Reflection_Emit_TypeBuilder) {
+               System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
+               g_assert (System_Reflection_Emit_TypeBuilder);
+       }
        if (method == NULL) {
-               method = mono_class_get_method_from_name (mono_defaults.monotype_class->parent, "IsAssignableFrom", 1);
+               method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
                g_assert (method);
        }
 
+       /* 
+        * The result of mono_type_get_object () might be a System.MonoType but we
+        * need a TypeBuilder so use klass->reflection_info.
+        */
+       g_assert (klass->reflection_info);
+       g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
+
        params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
 
-       res = mono_runtime_invoke (method, mono_type_get_object (mono_domain_get (), &klass->byval_arg), params, &exc);
+       res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
        if (exc)
                return FALSE;
        else
                return *(MonoBoolean*)mono_object_unbox (res);
 }
-